StatesController#中的NoMethodError为未定义的方法`update_column'创建

时间:2012-04-23 14:14:48

标签: ruby-on-rails ruby-on-rails-3

使用Rails 3.1,我有以下内容:

# state.rb
class State < ActiveRecord::Base
  belongs_to :country, :touch => true

  after_save :count_total_states

  private

  def count_total_states
    total_states = State.where(:country_id => self.country_id).count
    Country.where(:id => self.country_id).update_column(:state, total_states)
  end
end

# states_controller.rb
class StatesController < ApplicationController
  def create
    @country = Country.find(params[:country_id])
    @state = @country.states.build(params[:state])
    @state.position = State.where(:country_id => @country.id).maximum(:position).to_i + 1
    @state.save
  end
end

当我为state创建新对象时,出现以下错误:

NoMethodError in StatesController#create

undefined method `update_column' for #<ActiveRecord::Relation:0x1074b0e58>

返回控制器的方法是什么?请指教。

感谢。

2 个答案:

答案 0 :(得分:3)

此错误是因为:

Country.where(:id => self.country_id)

返回ActiveRecord::Relation个对象,而不是国家/地区。你可能应该做以下两件事之一:

Country.find(self.country_id).update_column(:state, total_states)

Country.where(:id => self.country_id).first.update_column(:state, total_states)

但是我建议使用第一个选项,因为它可以满足您的需求,通过ID查找记录。使用主键的位置有点时髦,你的目标是返回一个完全匹配,你知道它的ID,所以你应该直接抓住它。


注意:我还建议使用update_attribute而不是update_column,因为update_column会跳过所有验证。除非你真的不能,否则验证是个好主意。

更好的是,您正在使用的行为实际上已封装到称为“计数器缓存”的标准Rails实践中。请参阅此blog post和此Railscast,以了解实现目标的更好方法。

答案 1 :(得分:0)

正如@Andrew所提到的,为了能够正确地更新我的记录(使用位置),我必须添加“first”这里是代码snipet以防万一

[ruby sinatra]

我的观点(所以你可以看到这些形式的值)

    ...
    <form action="/device/<%= model.id %>/set-port-value" method="POST">
        <input name="number" type="hidden" value="27"/>
        <input name="value" type="hidden" value="11"/>
        <input type="submit" value="POST" />
    </form>
    ...

我的控制器

post '/device/:device_id/set-port-value' do
   # Updating one record:
   Port.where(number: params[:number]).first.update_column(:value, params[:value])

   @models = Port.all
   erb :'port/all'
end