0

I have an academic Q/A site which allows users to reference their questions (Questions) and answers (Answers) with scientific publications which are a third model, Citations.

Answers are a nested resource in Questions. At first I thought a polymorphic association with Citations would be good, but I have run into problems making paths dynamic in this case. A path could be for example

    /question/1/search_for_citation

Or

   /question/1/answer/2/search_for_citation

My question is simple. In this case would it be better to just bite the bullet and have a separate model for each i.e. Citation belongs to Question and say for example, Reference belongs to Answer and use a module to include common functionality. I wanted to do things the Rails way though...

GhostRider
  • 2,109
  • 7
  • 35
  • 53

2 Answers2

0

You can have citations nested in both questions and answers in your routes. You should probably also use shallow nesting.

baron816
  • 701
  • 4
  • 13
0

Assuming you have the following models:

class Question < ActiveRecord::Base
  has_many :answers, dependent: :destroy
  has_many :citations, as: :topic, dependent: :destroy
end

class Answer < ActiveRecord::Base
  belongs_to :question
  has_many :citations, as: :topic, dependent: :destroy
end

class Citation < ActiveRecord::Base
  belongs_to :topic, polymorphic: true
end

Then you can have nested resource-based routing like this:

resources :questions do
  resources :answers do
    resources :citations
  end
  resources :citations
end

However, it is advised that resources should never be nested more than 1 level deep (http://guides.rubyonrails.org/routing.html#limits-to-nesting), and this is where shallow nesting comes into play (http://guides.rubyonrails.org/routing.html#shallow-nesting).

If you redefine your routes like this:

resources :questions, shallow: true do
  resources :answers do
    resources :citations, only: [:index, :new, :create]
  end
  resources :citations
end

running rake routes will return the following:

     answer_citations GET    /answers/:answer_id/citations(.:format)         citations#index
                      POST   /answers/:answer_id/citations(.:format)         citations#create
  new_answer_citation GET    /answers/:answer_id/citations/new(.:format)     citations#new
        edit_citation GET    /citations/:id/edit(.:format)                   citations#edit
             citation GET    /citations/:id(.:format)                        citations#show
                      PATCH  /citations/:id(.:format)                        citations#update
                      PUT    /citations/:id(.:format)                        citations#update
                      DELETE /citations/:id(.:format)                        citations#destroy
     question_answers GET    /questions/:question_id/answers(.:format)       answers#index
                      POST   /questions/:question_id/answers(.:format)       answers#create
  new_question_answer GET    /questions/:question_id/answers/new(.:format)   answers#new
          edit_answer GET    /answers/:id/edit(.:format)                     answers#edit
               answer GET    /answers/:id(.:format)                          answers#show
                      PATCH  /answers/:id(.:format)                          answers#update
                      PUT    /answers/:id(.:format)                          answers#update
                      DELETE /answers/:id(.:format)                          answers#destroy
   question_citations GET    /questions/:question_id/citations(.:format)     citations#index
                      POST   /questions/:question_id/citations(.:format)     citations#create
new_question_citation GET    /questions/:question_id/citations/new(.:format) citations#new
            questions GET    /questions(.:format)                            questions#index
                      POST   /questions(.:format)                            questions#create
         new_question GET    /questions/new(.:format)                        questions#new
        edit_question GET    /questions/:id/edit(.:format)                   questions#edit
             question GET    /questions/:id(.:format)                        questions#show
                      PATCH  /questions/:id(.:format)                        questions#update
                      PUT    /questions/:id(.:format)                        questions#update
                      DELETE /questions/:id(.:format)                        questions#destroy

In other words, URL-wise, listing child objects, or creating or editing a new child object is always done in the context of the parent object, but showing, updating, deleting or editing an existing object is done directly on the object.

Thomas Hennes
  • 9,023
  • 3
  • 27
  • 36