保存せずにRails update_attributes?


386

レコードを保存しないupdate_attributesの代替はありますか?

だから私は次のようなことをすることができます:

@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save

ところで、私はできることを知っていますが@car.model = 'Sierra'、すべてを1行で更新したいと思います。


「レコードを保存しない」とはどういう意味ですか?
アナトリー

update_attributesはモデルをDBに保存します。似ていない方法がないのだろうか。
tybro0103 2011

3
属性は非破壊的な方法です。詳細については、APIを参照してください
Anatoly

3
update_column(name、value)を使用できます。saveを呼び出さずに、オブジェクトの単一の属性を更新します。1.検証はスキップされます。2.コールバックはスキップされます。3. updated_at / updated_on列は、その列が使用可能な場合は更新されません。apidock.com/rails/ActiveRecord/Persistence/update_column
Antoine

10
3.1以降の場合は、assign_attributes apidock.com
rails

回答:


597

私は、あなたが探しているものと考えていますassign_attributes

基本的にはupdate_attributesと同じですが、レコードは保存されません。

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name        # => "Bob"
user.is_admin?   # => false
user.new_record? # => true

モデルからこの行を貼り付けていないため、例は少し誤解を招く可能性があります:attr_accessible :is_admin, :as => :admin;)
Robin

@Robinまたは単に:attr_protected :is_admin。または:attr_accessible :nameこの例では、:is_adminが保護されていることがポイントです。また、例では示していません.assign_attributesが、で保護された属性を大量に割り当てようとすると、実際ActiveModel::MassAssignmentSecurity::Errorにが発生します。
Ajedi32 2012

ええ、でも私のラインはあなたがリンクしたドキュメントからのものです 例全体をコピー/貼り付けする必要があると言っているだけです。しかし、はい、保護されていると言えます。
Robin

@Robin例をもう少し具体的に更新します。ドキュメントの例も少し誤解を招くものです。user.assign_attributes({ :name => 'Josh', :is_admin => true })エラーメッセージが表示されたり、実際にユーザーの名前プロパティが設定されたりすることについては触れられていないためです。
Ajedi32 2012

7
assign_attributesはRails 3.1以降で使用できるため、古いバージョンのRailsを実行している場合は使用できません。
Haegin

174

assign_attributesまたはattributes=(同じです)を使用できます

メソッドチートシートの更新(Rails 6の場合):

  • update= assign_attributes+save
  • attributes= =のエイリアス assign_attributes
  • update_attributes =非推奨、エイリアス update

ソース:
https : //github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment .rb

別のチートシート:
http //www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet


1
明確で短い。ありがとう。
freemanoid 2014年

1
.attributes = valの場合、モデルが別のモデルのhas_oneとaccepts_nested_attributes_の場合、(idなしで)that_model_attributesを渡すと、永続化しなかった場合(例:保存)でも既存のhas_oneモデルが削除されます。しかし、assign_attributesはそのようには動作しません。
ClassyPimp 2016年

65

'attributes'メソッドを使用できます。

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

ソース:http : //api.rubyonrails.org/classes/ActiveRecord/Base.html

attributes =(new_attributes、guard_protected_attributes = true) 属性名に一致するキー(列名にも一致)を含むハッシュを渡すことにより、すべての属性を一度に設定できます。

guard_protected_attributesがtrue(デフォルト)の場合、attr_protectedマクロを使用して、機密属性をこの形式の大量割り当てから保護できます。または、attr_accessibleマクロでアクセスできる属性を指定することもできます。その場合、そこに含まれていないすべての属性を一括で割り当てることはできません。

class User < ActiveRecord::Base
  attr_protected :is_admin
end

user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username   # => "Phusion"
user.is_admin?  # => false

user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin?  # => true

7

保存せずにActiveRecordモデルに値を大量に割り当てるには、assign_attributesまたはattributes=メソッドを使用します。これらのメソッドはRails 3以降で使用できます。ただし、小さな違いと、バージョンに関連する注意すべき点があります。

どちらの方法もこの使用法に従います。

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

どちらのメソッドも検証を実行したり、コールバックを実行したりしないことに注意してください。コールバックと検証は、saveが呼び出されるれます。

Rails 3

attributes=assign_attributesRails 3 attributes=とは少し異なります。渡された引数がハッシュであることを確認し、ハッシュでない場合はすぐに戻ります。assign_attributesそのようなハッシュチェックはありません。のActiveRecord属性割り当てAPIドキュメントをattributes=参照してください。

次の無効なコードは、属性を設定せずに単に戻るだけで、静かに失敗します。

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

attributes= 割り当ては正常に行われたかのように静かに動作しますが、実際にはそうではありませんでした。

この無効なコードはassign_attributes、囲んでいる配列のハッシュキーを文字列化しようとすると、例外を発生させます。

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributesNoMethodError例外が発生しstringify_keys、最初の引数がハッシュではないことを示します。例外自体は実際の原因についてあまり情報を提供しませんが、例外が発生するという事実は非常に重要です。

これらのケースの唯一の違いは、一括割り当てに使用される方法です。attributes=暗黙的に成功し、assign_attributes例外が発生してエラーが発生したことを通知します。

これらの例は不自然に思えるかもしれませんが、ある程度ではありますが、このタイプのエラーは、APIからデータを変換するとき、または単に一連のデータ変換を使用しHash[]て最終のの結果を忘れたときにも簡単に発生します.map。50行以上のコードをいくつか維持し、属性割り当てから3つの関数を削除すると、失敗のレシピが得られます。

Rails 3のレッスンはこれです:の代わりに常に使用してください。assign_attributesattributes=

Rails 4

Rails 4では、attributes=は単にのエイリアスassign_attributesです。のActiveRecord属性割り当てAPIドキュメントをattributes=参照してください。

Rails 4では、どちらの方法も同じように使用できます。最初の引数としてハッシュを渡さないと、非常に役立つ例外が発生します。ArgumentError: When assigning attributes, you must pass a hash as an argument.

検証

の準備として割り当ての事前飛行を行っている場合はsave、保存前の検証にも関心があるかもしれません。これにはvalid?およびinvalid?メソッドを使用できます。どちらもブール値を返します。 valid?保存されていないモデルがすべての検証に合格した場合はtrueを、そうでない場合はfalseを返します。 invalid?単にの逆ですvalid?

valid? このように使用できます:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

これにより、を呼び出す前に、検証の問題を処理できますsave

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