Search code examples
ruby-on-railsnested-resources

Model belongs_to two models create action


I have three models: User, Question, and Answer, as follows:

Class Answer < ActiveRecord::Base
  belongs_to :user
  belongs_to :question
end

Class Question < ActiveRecord::Base
  belongs_to :user
  has_many :answers
end

Class User < ActiveRecord::Base
  has_many :questions
  has_many :answers
end

My main business logic lay on the idea that a user post a question, and other users answer it. I want to be able to track a question answers as well a user answers, something like: @user.answers and @question.answers.

The view contain the question content and the answer's form.

I'm able to track the user via devise current_user helper.

How the answers create action should look like? It's a bit confusing for me, as for a single association I would just use build.


Solution

  • question.rb #enable nested_attributes

     accepts_nested_attributes_for :answers, :reject_if => proc { |o| o['content'].blank? } #assuming Answer has `content` field to hold the answer. Or replace with exact one.
    

    routes.rb

    resources :questions do
      member do
        post :answer
      end
    end 
    

    Questions controller

    def answer
      @question = Question.find(params[:id])
      @answer = @question.answers.build(params[:answer])
      @answer.user_id = current_user.id
    
      respond_to do |format|
        if @answer.save
          format.html { redirect_to @question, notice: 'Question was successfully updated.' }
          format.json { head :no_content }
        else
          format.html { render action: "show" } #assuming your comment form is here.
          format.json { render json: @answer.errors, status: :unprocessable_entity }
        end
      end
    end
    

    Your answer form might look like this:

    <%= form_for(:answer, url: answer_question_path(@question)) do |f| %>
    
      <%= f.text_field :content, :placeholder => "Your Answer" %> #You may modify your answer fields here.
      <%= f.submit 'Answer' %>
    
    <% end %>