nested attributes, passing current_user.id to nest

2019-09-02 19:28发布

I have 3 models: User, Answer and Question.

user.rb

 has_many :questions
 has_many :answers

question.rb

 has_many :answers
 belongs_to :user
 accept_nested_attributes_for :answers

answer.rb

 belongs_to :question
 belongs_to :user

In questions/show.html.erb

 form_for @question do |f|
   f.fields_for :answers, @question.answers.build do |builder|
     builder.text_area, :body
   end

   f.submit
 end

Submit calls the questions#update action and, thanks to nested resources, will the new answer be saved in the database. I wonder: how can I save the user_id column for answer, in the database, after the question is submitted? Can I somehow pass current_user.id to answer's user_id column after submitting the form?

3条回答
贼婆χ
2楼-- · 2019-09-02 19:55

'current_user' is a devise helper method. it can be accessed in controllers n views directly. if i m not wrong, only the new answer should have the current_user.id Old answers should not be updated. u can do this as

f.fields_for :answers, @question.answers.build do |a|
  a.hidden_field :user_id, :value => current_user.id
  a.submit
查看更多
Luminary・发光体
3楼-- · 2019-09-02 20:05

You could do something like this in your controller's update action:

# questions_controller
def update
   params[:question][:answers_attributes].each do |answer_attribute|
     answer_attribute.merge!(:user_id => current_user.id)
   end

  if @question.update_attributes(params[:question])
    ...
  end
end

Another more simple solution would be to add the user_id to your form like this:

form_for @question do |f|
  f.fields_for :answers, @question.answers.build(:user_id => current_user.id) do |builder|
    builder.text_area, :body
    builder.hidden_field :user_id # This will hold the the user id of the current_user if the question is new
  end

  f.submit
end

The problem with this approach is that users would be able to edit the value through a HTML source code inspector (like in chrome), and thereby set the user to someone else. You could of course validate this in some way, but that too would be a bit complex.

查看更多
叛逆
4楼-- · 2019-09-02 20:12

You have to pass the user parameter in your controller's create action (also you should build your nested attributes in the controller):

def new
  @question = Question.new
  @question.answers.build
end

def create
  @question = current_user.questions.new(params[:questions])
  //The line below is what will save the current user to the answers table 
  @question.answers.first.user = current_user

  ....
end 

Your view's form should therefore look like:

form_for @question do |f|
   f.fields_for :answers do |builder|
     builder.text_area, :body
 end

 f.submit

end

查看更多
登录 后发表回答