Accepts_nested_attributes_for 的构建参数存在问题

发布于 2024-08-30 20:03:20 字数 1960 浏览 10 评论 0原文

我正在尝试将 user_id 添加到由父控制器构建的嵌套属性中,但它似乎没有达到预期的效果?

IE。我有一个名为 Place.rb 的模型,其中 accepts_nested_attributes_for :reviewshas_many :reviews, :as => :可审查,:依赖 => :destroy

嵌套属性工作正常,我在 Places 控制器中构建它,如下所示...

新操作

@review = @place.reviews.build(:user_id => current_user.id)

创建操作,

params[:place].merge(:user_id => current_user.id)
params[:place][:reviews_attributes].merge!(:user_id => current_user.id)* bad
@place = Place.new(params[:place])

这是原始的,用于位置模型获取 user_id,现在我需要嵌套的 user_id也评论模型。地点和评论都有 user_ids 可能看起来很奇怪,但人们可以为同一个地方添加新评论...

可能像这样,但不起作用:

@place = Place.new(params[:place].merge(:user_id => current_user.id, :reviews_attributes => { :user_id => current_user.id } ))

收到错误:undefined methodwith_in Different_access' for 3:Fixnum`

@place = Place.new(params[:place].merge(:user_id => current_user.id, :reviews_attributes => { "0" =>  { :user_id => current_user.id }}))

添加正确的 user_id 但用 NULL 替换评论的内容;-(

我之前通过表单添加用户,但想通过控制器执行此操作,以便它只在创建时添加 user_id ,因为某个特定的评论可能会被其他人更新,并且我不希望更新更改原始作者的 user_id...

旧方法有效:

<%= e.label :content, "Review" %><br />
<%= e.text_area :content, :rows => 20, :class => 'jquery_ckeditor' %><br />
<%= e.hidden_field :user_id, :value => current_user.id %> #want to remove this line

但是通过控制器,带有选项的构建方法没有效果?我可以不通过构建来执行此操作吗?

日志中的输出:

    Parameters: {"commit"=>"Submit", "action"=>"create", "city_id"=>"prague",
 "controller"=>"places", "place"=>{"address"=>"fsdfsdf", "name"=>"sdfsdfsd",
 "reviews_attributes"=>{"0"=>{"content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf sdfsdfsdf</p>\r
\n"}}, "website"=>"", "city_id"=>"1036", "place_type"=>"1"}}

I'm trying to add the user_id to a nested attribute that gets built by a parent controller but it doesn't seem to have the desired effect?

Ie. I have a model called Place.rb which accepts_nested_attributes_for :reviews and has_many :reviews, :as => :reviewable, :dependent => :destroy

The nested attribute works fine and I build it inside the Places controller like so...

new action

@review = @place.reviews.build(:user_id => current_user.id)

create action

params[:place].merge(:user_id => current_user.id)
params[:place][:reviews_attributes].merge!(:user_id => current_user.id)* bad
@place = Place.new(params[:place])

this is the original, for the place model to get a user_id, now i need the user_id for the nested reviews model as well. It might seem odd that places and reviews both have user_ids, but people can add new reviews for the same place...

possibly like this but doesn't work:

@place = Place.new(params[:place].merge(:user_id => current_user.id, :reviews_attributes => { :user_id => current_user.id } ))

get the error: undefined methodwith_indifferent_access' for 3:Fixnum`

or

@place = Place.new(params[:place].merge(:user_id => current_user.id, :reviews_attributes => { "0" =>  { :user_id => current_user.id }}))

which adds the correct user_id but replaces the content of the review with NULL ;-(

I was previously adding the user thru the form, but would like to do it thru the controller so that it only adds the user_id on creation, as a particular review might get updated by someone else and i don't want the update changing the user_id from the original writer...

old way which works:

<%= e.label :content, "Review" %><br />
<%= e.text_area :content, :rows => 20, :class => 'jquery_ckeditor' %><br />
<%= e.hidden_field :user_id, :value => current_user.id %> #want to remove this line

but thru the controller the build method with options has no effect? Any ideas? Can I not do this thru the build?

The output in log:

    Parameters: {"commit"=>"Submit", "action"=>"create", "city_id"=>"prague",
 "controller"=>"places", "place"=>{"address"=>"fsdfsdf", "name"=>"sdfsdfsd",
 "reviews_attributes"=>{"0"=>{"content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf sdfsdfsdf</p>\r
\n"}}, "website"=>"", "city_id"=>"1036", "place_type"=>"1"}}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

回忆追雨的时光 2024-09-06 20:03:20

试试这个:

params[:place][:user_id] = current_user.id
params[:place][:reviews_attributes].each do |key, review|
  review[:user_id] = current_user.id
end if params[:place][:reviews_attributes]

Try this:

params[:place][:user_id] = current_user.id
params[:place][:reviews_attributes].each do |key, review|
  review[:user_id] = current_user.id
end if params[:place][:reviews_attributes]
紫﹏色ふ单纯 2024-09-06 20:03:20

假设您将 params[:review] 作为属性的哈希值,则需要进行合并!

params[:review].merge!(:user_id => current_user.id)
@review = @place.reviews.build(params[:review])

编辑:
我还假设您将使用 this is on create 方法。

编辑#2:
它不适用于 new 方法,因为正如您可以在 railsapi.com,构建方法

“仅当关联对象
已经存在,如果为零则不存在!”

编辑#3:
我不确定这是否是最好的方法,但我在这里进行了测试并且它有效...

您有以下参数:

{"commit"=>"Submit", "action"=>"create", "city_id"=>"prague",
   "controller"=>"places", "place"=>{"address"=>"fsdfsdf", "name"=>"sdfsdfsd",
   "reviews_attributes"=>{"0"=>{"content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf 
   sdfsdfsdf</p>\r\n"}}, "website"=>"", "city_id"=>"1036", "place_type"=>"1"}}

因此您可以通过这种方式访问​​评论的属性: params[:place][:reviews_attributes]< /code> 并且,要合并 user_id 属性,您可以执行以下操作:

params[:place][:reviews_attributes].each_value {
   |v| v.merge!(:user_id => current_user.id) 
}

现在 params[:place][:reviews_attributes] 看起来像这个示例:

{"0"=>{
   "user_id"=>"1",
   "content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf sdfsdfsdf</p>\r\n"
}}

Assuming you have params[:review] as the attributes' hash, you need to do a merge!:

params[:review].merge!(:user_id => current_user.id)
@review = @place.reviews.build(params[:review])

Edit:
I'm also assuming you'll use this is on create method.

Edit #2:
It's not gonna work on new method because, as you can find at railsapi.com, the build method

"only works if an associated object
already exists, not if it’s nil!"

Edit #3:
I'm not sure if this is the best way, but I tested here and It worked...

You have this parameters:

{"commit"=>"Submit", "action"=>"create", "city_id"=>"prague",
   "controller"=>"places", "place"=>{"address"=>"fsdfsdf", "name"=>"sdfsdfsd",
   "reviews_attributes"=>{"0"=>{"content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf 
   sdfsdfsdf</p>\r\n"}}, "website"=>"", "city_id"=>"1036", "place_type"=>"1"}}

So you can access reviews' attributes this way: params[:place][:reviews_attributes] and, to merge the user_id attribute, you can do:

params[:place][:reviews_attributes].each_value {
   |v| v.merge!(:user_id => current_user.id) 
}

Now params[:place][:reviews_attributes] looks like this example:

{"0"=>{
   "user_id"=>"1",
   "content"=>"<p>\r\n\tsdfsdfsdfsdfsdfsdfsdf sdfsdfsdf</p>\r\n"
}}
小矜持 2024-09-06 20:03:20

您可能想也可能不想在包含 user_id 的表单中添加隐藏字段。那么 params 哈希值就已经有了。如果您担心被篡改,可以将其与 current_user.id 进行比较。话又说回来,也许这就是你一开始尝试这种方式的原因?

You may or may not want to add a hidden field in the form that includes the user_id. Then the params hash will already have the value. If you're worried about tampering, you could compare it to the current_user.id. Then again, maybe that's why you're trying it this way to begin with?

ゞ记忆︶ㄣ 2024-09-06 20:03:20

也许您使用的 form_for 语法很差。看了这个之后我已经退出使用hidden_​​fields: http://apidock.com/rails/ActionView /Helpers/FormHelper/form_for

和此评论:(上帝保佑你,nachocab!)

nachocab - 2008 年 11 月 2 日参数
hash自动获取模型id

params 哈希值自动获取
填充每个模型的 id
它被传递给 form_for。如果我们
正在创作一首歌曲
现有相册:

网址:/albums/209/songs/new form_for
[@album, @song] 做|f|
...
f.提交“添加”结束

参数哈希将是:

params = {"提交"=>"添加",
"authenticity_token"=>"...",
“album_id”=>“209”,
“歌曲”=>{“song_attributes”=>{...}}
}

所以,在歌曲控制器中你可以
在 before_filter 中使用此 album_id:

过滤器之前:查找专辑
受保护的 def find_album
@album = Album.find(params[:album_id]) end

如果您只这样做:

form_for @song do |f|

你会得到这个参数哈希:

params = {"提交"=>"添加",
"authenticity_token"=>"...",
“歌曲”=>{“song_attributes”=>{...}}
}

Maybe you are using form_for with a poor syntax. I have quit using hidden_fields after looking at this: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for

and this comment: (God Bless You, nachocab!)

nachocab - November 2, 2008 params
hash gets the model id automatically

The params hash gets automatically
populated with the id of every model
that gets passed to form_for. If we
were creating a song inside an
existing album:

URL:/albums/209/songs/new form_for
[@album, @song] do |f|
...
f.submit "Add" end

The params hash would be:

params = {"commit"=>"Add",
"authenticity_token"=>"...",
"album_id"=>"209",
"song"=>{"song_attributes"=>{...}}
}

So, in the songs_controller you could
use this album_id in a before_filter:

before_filter :find_album
protected def find_album
@album = Album.find(params[:album_id]) end

If you only did this:

form_for @song do |f|

You would get this params hash:

params = {"commit"=>"Add",
"authenticity_token"=>"...",
"song"=>{"song_attributes"=>{...}}
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文