Есть несколько стратегий, которые работают довольно хорошо. Вы можете иметь вызов в контроллере, который прикрепляет пользователя к созданному комментарию:
def create
@comment = @post.comments.build(params[:comment])
@comment.user = session_user
@comment.save!
redirect_to(post_path(@post))
rescue ActiveRecord::RecordInvalid
# Take appropriate action, such as show comment create form
render(:action => 'new')
end
Другой способ - использовать что-то вроде model_helper (http://github.com/theworkinggroup/model_helper/) для предоставления доступа к свойствам контроллера в среде модели:
class ApplicationController < ActionController::Base
# Makes the session_user method callable from the ActiveRecord context.
model_helper :session_user
end
class Comment < ActiveRecord::Base
before_validation :assign_session_user
protected
def assign_session_user
if (self.user.blank?)
self.user = session_user
end
end
end
Этот метод более автоматический, но за счет прозрачности и, возможно, усложняет среду юнит-тестирования.
Третий подход - объединить параметры при вызове create:
@comment = @post.comments.build((params[:comment] || { }).merge(:user => session_user))
Недостатком этого является то, что некоторые свойства вашей модели работают не очень хорошо, как, вероятно, должно быть в любой производственной среде.
Еще одна хитрость заключается в создании метода класса, который помогает создавать вещи для вас:
class Comment < ActiveRecord::Base
def self.create_for_user(user, params)
created = new(params)
created.user = user
created.save
created
end
end
Это вызывается на отношения и будет строить в правильной области:
@comment = @post.comments.create_for_user(session_user, params[:comment])