Ruby on Rails - 将父对象添加到子级?

时间:2010-01-18 19:54:56

标签: ruby-on-rails parent

我有一个用户存储在会话中,我想将其添加为评论的所有者。我没有为user_id设置隐藏字段,而是在评论保存在控制器中之前添加用户。

最好的方法是什么?

@comment = @post.comments.create(params[:comment])

感谢。

2 个答案:

答案 0 :(得分:1)

有一些策略运作得相当好。您可以在控制器中调用将用户钉在已创建的注释上:

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

这种方法更自动,但代价是透明,可能会使您的单元测试环境复杂化。

第三种方法是在创建调用中合并参数:

@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])

答案 1 :(得分:1)

首先,出于安全原因,您可能希望保护评论的user_id属性,因此您的模型中应该包含以下内容:

attr_protected :user_id

或者,使用attr_accessible并列出可以通过质量分配设置的所有属性(即Comment.create(...)@comment.update_attributes(...))。然后,因为你必须通过赋值来分配,你的控制器将如下所示:

@comment = @post.comments.new(params[:comment])
@comment.user_id = current_user.id
@comment.save

它不是那么光滑,但是有必要让某人无法提交假的user_id值。