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国ではなく、オブジェクトを返します。代わりに、次の 2 つのいずれかを実行する必要があります。

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

また

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

ただし、最初のオプションをお勧めします。これは、ID でレコードを検索するという、本当に必要なことを行うためです。主キーで Where を使用するのは一種のファンキーです。目的は、完全に一致するものを 1 つだけ返すことであり、その ID を知っているので、直接取得する必要があります。


注:すべての検証をスキップするため、update_attributeの代わりにもお勧めします。本当にできない場合を除き、検証することをお勧めします。update_columnupdate_column

さらに良いことに、使用している動作は、実際には「カウンター キャッシュ」と呼ばれる標準的な Rails プラクティスにカプセル化されています。目標を達成するためのより良い方法のデモンストレーションについては、このブログ投稿とこのRailscastを参照してください。

于 2012-04-23T14:19:56.373 に答える
0

@Andrewが言及したように、レコードを(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 に答える