如何在创建对象之前修改参数

How to modify params before creating an object

我正在使用嵌套属性创建一个 Photo 和一个 Comment 对象。我想在评论上设置作者,嵌套在照片里面。

参数如下:

photo: {
  file: 'hi.jpg',
  comments_params: [
    { content: "hello world!" }
  ]
}

但我想在评论中添加作者。

  # ...
  comments_params: [
    { content: "hello world!", author: current_user }
  ]
  # ...

最简单的方法是什么?我的控制器代码如下所示。

@photo = Photo.new(photo_params)
@photo.save!

private

def photo_params
  params.require(:photo).permit(:file, comments_attributes: [:content])
end

我可以通过在使用 strong_parameters 过滤参数后操纵它们来做到这一点(伪代码,但想法成立),但我宁愿不这样做。

photo_params[:comments_attributes].each do |comment|
  comment[:author] = current_user
end

但是这样感觉有点不对

您可以在评论表单中添加隐藏字段。

<%= f.hidden_field :user_id, :value => current_user.id %>

我不认为你不想做的方式有什么问题。

您或许还可以以某种方式使用标准 Hash#merge or merge!, or ActiveSupport's deep_merge or deep_merge!

事实上,评论是一个可能包含许多评论的数组,因此很难很好地做到这一点。

我想我会制作原始参数的副本,而不是就地编辑它们——您认为这是错误的吗? ActiveSupport's deep_dup 可能会有帮助。

怎么样:

photo_params = photo_params.deep_dup
photo_params[:comments_attributes] = photo_params[:comments_attributes].collect {|c| c.merge(:author => :current_user)}
@photo = Photo.new(photo_params)
...

我不确定那是否真的更好。但也许它会让您了解一些可供您使用的工具。

您可以将 author 分配给现在存在的对象,而不是弄乱参数:

@photo = Photo.new(photo_params)
@photo.comments.select(&:new_record?).each {|c| c.author = current_user }
@photo.save!