在“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 对象的主要内容,如果未能解决你的问题,请参考以下文章

spring的注入和直接new一个对象有啥不同?

MFC技巧

OOP:将对象与将属性传递给方法

中间件之间传递信息以及将信息发送给模板

如何将剃刀视图模式属性值传递给 javascript 函数

将道具值传递给axios中的url不起作用