Rails:update_attributeとupdate_attributes


255
Object.update_attribute(:only_one_field, "Some Value")
Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

これらは両方とも、更新をARに明示的に指示する必要なく、オブジェクトを更新します。

Rails APIは言う:

update_attribute

単一の属性を更新し、通常の検証手順を実行せずにレコードを保存します。これは、既存のレコードのブールフラグに特に役立ちます。検証モジュールが混合されると、Baseの通常のupdate_attributeメソッドがこれに置き換えられます。これはデフォルトです。

update_attributes

渡されたハッシュからすべての属性を更新し、レコードを保存します。オブジェクトが無効な場合、保存は失敗し、falseが返されます。

したがって、オブジェクトを検証したくない場合は、update_attributeを使用する必要があります。before_saveにこのアップデートがあるとどうなりますか?

私の質問は、update_attributeも保存前または検証のみをバイパスするかどうかです。

また、update_attributesにハッシュを渡すための正しい構文は何ですか?一番上の私の例を確認してください。


なぜコールバックupdate_attribute内にステートメントを置きたいのbefore_saveですか?これには理由がありません。
Daniel Pietzsch、

1
更新されたオブジェクトの量に基づいて更新する必要があるオブジェクトがあります。より良い方法は何ですか?
thenengah

更新する必要があるオブジェクトは、保存しているオブジェクトの属性だと思いますか?はいの場合、それらを設定するだけで、保存されたオブジェクトとともに更新されます(before_saveコールバック内で設定されているため)。Feの代わりにupdate_attribute(:discount, 0.1) if amount > 100できるdiscount = 0.1 if amount > 100update_attribute呼び出しsave文が内部にあることから、この場合には不要であるオブジェクト、上のbefore_saveコールバックと、とにかく保存されます。私はそれが理にかなっていると思います。
Daniel Pietzsch、

はいといいえ。ただし、参照しているオブジェクトのステータスは、保存前に処理できない他の条件に依存します。
thenengah

3
注として、これらのメソッドは検証をスキップしますが、after_saveなどのコールバックを実行します...
rogerdpack

回答:


328

を参照してくださいupdate_attribute。ソースの表示をクリックすると、次のコードが表示されます

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def update_attribute(name, value)
2615:         send(name.to_s + '=', value)
2616:         save(false)
2617:       end

そして今update_attributesあなたが得るそのコードを参照して見てください

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2621
2621:       def update_attributes(attributes)
2622:         self.attributes = attributes
2623:         save
2624:       end

2つの違いはupdate_attribute用途ですがsave(false)update_attributes用途saveまたはあなたは言うことができますsave(true)

長い説明で申し訳ありませんが、私が言いたいことが重要です。save(perform_validation = true)perform_validationfalseの場合、に関連付けられているすべての検証をバイパスします(スキップが適切な単語になります)save

2番目の質問

また、update_attributesにハッシュを渡すための正しい構文は何ですか?一番上の私の例を確認してください。

あなたの例は正しいです。

Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

または

Object.update_attributes :field1 => "value", :field2 => "value2", :field3 => "value3"

または、ハッシュですべてのフィールドのデータと名前を取得する場合は、params[:user]ここで

Object.update_attributes(params[:user])

7
少なくとも、コールバックに関するステートメントが正しくありませんRails 3。それはソースのコメントで「コールバックが呼び出される」と非常にはっきり言っています。
Batkins 2013年

私は@Batkinsが言うことの2番目です
Raf

3
@Batkinsはまだ検証が実行されていません-これは最も重要な部分です:)
Tigraine '29年

1
上記のリンクは、少なくともRails 5.1以降は正確ではなくなりました。これらのメソッドはActiveRecord :: Persistenceに移動されました。ここで更新された情報を見つけることができます:update属性とここ update_attributes注:update_attributesは現在のエイリアスですupdate
tgf

74

ヒント: update_attributeは、Commit a7f4b0a1を介してRails 4で廃止される予定です。にupdate_attribute有利に削除しupdate_columnます。


45
これはもはや真実ではありません。メソッドが再度追加されました。参照してくださいgithub.com/rails/rails/pull/6738#issuecomment-39584005
デニス・

20
update_attributeスキップ検証が、点コールバックは、update_column検証、コールバックおよび習慣更新の両方をスキップし:updated_atupdate両方のコールバックおよび検証を尊重し、正常な機能である
モハメドAbuShady

2
彼らはすでに決心するでしょうか。reset_column、update_columnも非推奨です。
ahnbizcad 2014

2
update_columnは非推奨ではありませんが、推奨されupdate_columns(name: value)ます。reset_column削除されました。
onebree 2015

15

update_attribute

このメソッドは、モデルベースの検証を呼び出さずにオブジェクトの単一の属性を更新します。

obj = Model.find_by_id(params[:id])
obj.update_attribute :language, java

update_attributes

このメソッドは、単一のオブジェクトの複数の属性を更新し、モデルベースの検証も渡します。

attributes = {:name => BalaChandar”, :age => 23}
obj = Model.find_by_id(params[:id])
obj.update_attributes(attributes)

この回答が、アクティブレコードのどのメソッドをいつ使用するかが明確になることを願っています。


12

またupdate_attribute、指定した属性のみを更新attr_accessibleする一括割り当てメソッドupdate_attributesとは対照的に、では、更新する必要のある属性を更新するためにホワイトリストに登録する必要はありませんattr_accessible


8

update_attribute単にモデルの1つの属性のみを更新しますが、update_attributesメソッドで複数の属性を渡すことができます。

例:

user = User.last

#update_attribute
user.update_attribute(:status, "active")

検証に合格

#update_attributes
user.update_attributes(first_name: 'update name', status: "active")

検証が失敗しても更新されません。


とてもよく説明されました。ありがとう!
Diego Somar 2017年

6

素晴らしい答え。ruby 1.9以降については、update_attributesに新しいハッシュ構文を使用できる(そしてそうすべきだと思う)ことに注意してください。

Model.update_attributes(column1: "data", column2: "data")

6

属性または更新レコード(Rails 4に更新)update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/を割り当てるためのすべての可能な方法について、このブログ投稿をご覧ください。たとえば、検証の実行、オブジェクトのupdated_atへのタッチ、コールバックのトリガーなどの側面が異なります。

OPの質問への回答として、update_attributeコールバックをバイパスしないでください。


確かに、私は答えを修正しました。フィードバックをお寄せいただきありがとうございます。
adamliesko 2015

4

update_attributeupdate_attributes似ていますが、大きな違いが1つupdate_attribute あります。検証を実行しません

また:

  • update_attribute単一の属性を持つレコードを更新するために使用されます。

    Model.update_attribute(:column_name, column_value1)
  • update_attributes複数の属性を持つレコードを更新するために使用されます。

    Model.update_attributes(:column_name1 => column_value1, :column_name2 => column_value2, ...)

これらの2つの方法は、名前と機能が似ているため、非常に混乱しやすいものです。したがって、update_attributeが削除されupdate_columnます。

これで、Rails4では、Model.update_column(:column_name, column_value)の場所で使用できます。Model.update_attribute(:column_name, column_value)

ここをクリックして、に関する詳細情報を入手してくださいupdate_column


4

あなたの質問に答えるために、update_attribute保存前の「検証」をスキップしますが、それでも他のようなコールバックを実行しますafter_save。したがって、本当に「列を更新し、AR cruftをスキップする」場合は、(明らかに)を使用する必要があります。

Model.update_all(...)https://stackoverflow.com/a/7243777/32453を参照してください


2

最近、私はに走ったupdate_attributeupdate_attributes、および検証の問題ので、同じような名前なので、異なる動作なので、混乱を。

ハッシュを渡してupdate_attribute検証をバイパスするには、次のようにします。

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)

1

あなたの質問は、before_saveにupdate_attributeがあると無限ループ(before_saveコールバックでのupdate_attribute呼び出しのループが最初にupdate_attribute呼び出しによってトリガーされる)につながるかどうかだと思います

実際にはレコードを保存しないため、before_saveコールバックをバイパスすることは間違いありません。を使用して、検証をトリガーせずにレコードを保存することもできます

Model.save false

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.