在“new”和“create”之间将属性传递给 belongs_to Rails 对象
Posted
技术标签:
【中文标题】在“new”和“create”之间将属性传递给 belongs_to Rails 对象【英文标题】:Passing attributes into a belongs_to Rails object in between "new" and "create" 【发布时间】:2012-11-30 22:32:57 【问题描述】:我确信这是一个很容易解决的问题,部分原因是我自己缺乏知识,但我进行了一些搜索,无法找到解决问题的正确方法。
在我的情况下,我有一个类 Product 有许多 Review 对象。评论也属于用户。假设我已经正确定义了我的模型,我很难弄清楚如何正确地将 :product_id 变量传递到评论中,以便在提交时将给定的评论与给定的产品联系起来。
到目前为止,我所拥有的是一个显示产品信息的视图以及<%= link_to 'Review Product', new_review_path(:product_id => @product.id) %>
形式的 link_to。添加新评论的结果视图表单(旨在用于该产品)看起来至少有些正确,因为 URL 显示为 http://localhost:3000/reviews/new?product_id=1 .正如我所提到的,我已经完成了先前的搜索,并且已经提供了对我的问题的类似答案,但它并没有解决问题,因为当我显示 @review
实例变量的值时,每个属性都是 nil。
在我的 reviews_controller.rb 文件中,我可以分配这些变量 -- 至少在 new 操作的表单中,通过执行类似于以下的操作:
@review = Review.new(:product_id => params[:product_id])
我还可以通过执行类似的操作并传递 current_user 变量(由设计 gem 处理)来分配 user_id 变量。我知道 Rails 使用的 create 操作通常会根据我阅读的所有内容创建变量的新实例。但是,这样做会导致数据丢失,但我在表单中输入的变量除外。从技术上讲,我应该能够在 create 操作中传递 current_user 变量,但我无法传递(或不知道如何传递)产品变量。对于它的价值,我现在没有使用任何类型的嵌套路由,但我不知道这是否是一个直接的解决方案。
如果有人对我可以做些什么来解决这个问题有更好的理解,我将不胜感激。正如我所暗示的,我确信这是一个业余错误。
附:如果问题的措辞很尴尬,我深表歉意,因为我不确定描述它的最佳方式。
【问题讨论】:
你可以看看this guide关于嵌套属性。在我看来,您应该使用嵌套路由。 我会看看的。我以前实际上是这样做的,但也许我没有以能够解决我的问题的方式实现它。 我遇到过你的情况-here is my case 【参考方案1】:如果您不使用 Qumara 建议的嵌套路由(我同意),那么您需要将以下内容添加到 app/views/reviews/new.html.erb 中,以便它可用于您的创建操作。
<%= r.hidden_field :product_id %>
当然请记住,这意味着如果我知道产品 ID,我可以破解您的表单并将我的评论设置为我想要的任何产品。所以你可能想考虑一下......
【讨论】:
【参考方案2】:嵌套资源路由可能是最好的方法。
@PhilipHallstrom 的方式适用于 form
元素,但如果您正在寻找 Restful 方法:
# Add nested resource route
# /config/routes.rb
resources :products do
resources :reviews
end
# In your 'products/show.erb.html'; @product will be the instance you want to review
<%= link_to 'Review Product', new_product_review_path(@product) %> # gets you to ReviewController#new
# In your ReviewsController#new
@product = Product.find(params[:product_id])
@review = @product.reviews.new #this should have product_id
# In your 'reviews/new.erb.html'
<% form_for [ @product, @review ] %> # gets you to ReviewController#create
# In your ReviewsController#create
@product = Product.find(params[:product_id])
@review = @product.reviews.new(params[:review]) # params from the previous form
@review.user = current_user
@review.save
至于通过无效的表单参数传递current_user
或@product
。从技术上讲,您不能通过 HTTP 传递实际的 Ruby 对象。
current_user
仍将存在于控制器中,因此没有意义,而且对安全性不利。
@product
你需要从控制器查询数据库,使用product_id
【讨论】:
以上是关于在“new”和“create”之间将属性传递给 belongs_to Rails 对象的主要内容,如果未能解决你的问题,请参考以下文章