As many times that I've tried to do rails testing, you'd think I had figured it out by now - I haven't.
The latest approach is using minitest - at least it's mainly Ruby and not a bunch of DSL that is learning yet another language with what seems like hundreds of methods. Now I may have dug myself into a hole with my latest experiment, but I kind of like what I tried to accomplish. It's a combination of nested resources, including some polymorphic resources. It is also using Pundit for authorization.
The models define a hierarchical entity (think of a corporation or government agency such as the forest service, or in my case the VFW hierarchy)
Basic Modelsclass Department < ActiveRecord::Base
has_many :districts, dependent: :destroy
has_many :posts, through: :districts
has_many :reports, through: :posts
has_many :officers, as: :fillable, dependent: :destroy
has_many :markups, as: :markupable, dependent: :destroy
has_many :users, as: :loginable, dependent: :destroy
end
class District < ActiveRecord::Base
belongs_to :department
has_many :posts, dependent: :destroy
has_many :reports, through: :posts
has_many :officers, as: :fillable, dependent: :destroy
has_many :markups, as: :markupable, dependent: :destroy
has_many :users, as: :loginable, dependent: :destroy
end
class Post < ActiveRecord::Base
belongs_to :district
has_one :department, through: :district
has_many :members, dependent: :destroy
has_many :officers, as: :fillable, dependent: :destroy
has_many :reports, dependent: :destroy
has_many :markups, as: :markupable, dependent: :destroy
has_many :users, as: :loginable, dependent: :destroy
end
class User < ActiveRecord::Base
belongs_to :loginable, polymorphic: true
end
class Officer < ActiveRecord::Base
belongs_to :fillable, polymorphic: true
end
class Report < ActiveRecord::Base
belongs_to :post
end
As in most entities like this, the bottom does all the work (submit reports, etc) and the upper levels just manages, summarizes and reports.
This is a semi closed system in that you have to login as at least a 'Guest' where you can look, but not touch. Each level has Officers (employees), and Markups (news, post, etc). The User is a polymorphic relation belonging to one of the entities (Department, District, or Post).
My main routes are basically shallow routing except I use Pundit for scoping:
resources :departments do
resources :officers,only: [:new, :create]
resources :markups,only: [:new, :create]
member do
get :reports_summary
end
end
resources :districts do
resources :officers,only: [:new, :create]
resources :markups,only: [:new, :create]
member do
get :reports_summary
end
end
resources :posts do
resources :officers,only: [:new, :create]
resources :markups,only: [:new, :create]
resources :reports,only: [:new, :create]
resources :members,only: [:new, :create]
member do
get :reports_menu
get :reports_summary
end
end
resources :officers, only: [:index, :show, :edit, :update, :destroy]
resources :markups, only: [:index, :show, :edit, :update, :destroy]
resources :reports, only: [:index, :show, :edit, :update, :destroy]
resources :members, only: [:index, :show, :edit, :update, :destroy]
Just looking at Post Officers, the generated routes are:
post_officers_path POST /posts/:post_id/officers(.:format) officers#create
new_post_officer_path GET /posts/:post_id/officers/new(.:format) officers#new
My problem is getting controller tests to work without taking the rest of my life to figure it out! I did use scaffold the generate the models and tests. I'm beginning to go to the side that says controller tests are a repetitive waste of time and concentrate on integration tests. My major problem is :new and :create tests for polymorphic associations like Officers. My old blunt force testing works fine (knowing that it is not the best approach) and routes all work. The controller new and create tests will fail with ActionController::UrlGenerationError: No route matches {:action=>"/posts/980190962/officers/new", :controller=>"officers"}
or No route matches {:action=>"new", :controller=>"officers"}
Even hardwiring the route for a new Post Officers with:
def test_new_post
get "/posts/#{@resource.id}/officers/new"
assert_response :success
end
fails.
I was mainly looking at the controller test to do the basic CRUD stuff and Authorization, but I think its easier to test Authorization in a integration test, especially if there are different roles to do different stuff - but I should be able to figure this out. I've looked at what seems like hundreds of posts on stackoverflow, but none seem to address polymorphic nested resources.