1

使用 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>

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

谢谢。

4

2 回答 2

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 查找记录。使用带主键的 Where 有点时髦,您的目标是只返回一个完全匹配并且您知道它的 ID,因此您应该直接获取它。


注意:我也建议update_attribute不要update_column,因为update_column跳过所有验证。验证是个好主意,除非你真的不能。

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

于 2012-04-23T14:19:56.373 回答
0

正如@Andrew 提到的,我必须添加“first”才能正确更新我的记录(使用 where),这是代码片段,以防万一

[红宝石辛纳屈]

我的观点(这样你就可以看到这些表单的值)

    ...
    <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
于 2016-04-10T06:47:04.227 回答