我正在尝试使用Rails 5中的Product
归档link_to
。
在视图中:
<% @products.each do |product| %>
<%= link_to product_path(product, "product[archived]" => true),
:method => :put,
data: { confirm: 'Sure?' } do %>
<i class="fa fa-archive color-danger" aria-hidden="true"></i>
<% end %>
<% end %>
但是点击链接后我ProductsController
会抛出以下错误:
undefined method `to_sym' for {:archived=>false}:Hash Did you mean? to_s to_yaml to_set
错误指向if @product.update(product_params)
行。完整更新方法是:
def update
@product = Product.find(params[:id])
puts @product.id
if @product.update(product_params)
redirect_to @product
else
render 'edit'
end
end
修改
实际上,违规行是我Product
模型中写得不好的验证。
我有:validates_uniqueness_of :code, :scope => [:archived => false]
,应该是validates_uniqueness_of :code, conditions: -> { where.not(archived: true) }
。
事后看来这是一个愚蠢的错误,但现在我想知道为什么它会抛出这么奇怪的错误,更糟糕的是,错误发生在控制器中 ......
答案 0 :(得分:0)
验证的scope
属性需要您的模型中的单个属性或属性数组,例如
class Product < ApplicationRecord
validates_uniqueness_of :code, :scope => :archived
end
事实证明,根据我上面的示例,包括:scope
选项adds a where clause during the validation看起来像where(:archived => false)
。
从原始代码validates_uniquesness_of :code, :scope => { :archived => false }
开始,这会导致范围执行where({:archived => false} => nil)
。您可以看到where
的哈希参数肯定是关闭的。
稍后在堆栈中,ActiveRecord
将尝试将参数哈希中的键转换为带有to_sym
的符号,并将该键作为Product
模型上的属性查找。但是,这种情况下的关键是散列{:archived=>false}
,它不响应to_sym
,这里会引发未定义的方法错误。
错误“出现”在控制器中的原因是因为控制器中的行product.update(product_params)
是调用链的开头,导致在模型中调用错误验证,您已确定是错误的来源。