Rails 5 - 无法使用link_to更新单个属性,未定义方法`to_sym'

时间:2017-08-08 19:33:13

标签: ruby-on-rails ruby-on-rails-5

我正在尝试使用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) }

事后看来这是一个愚蠢的错误,但现在我想知道为什么它会抛出这么奇怪的错误,更糟糕的是,错误发生在控制器中 ......

1 个答案:

答案 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)是调用链的开头,导致在模型中调用错误验证,您已确定是错误的来源。