web-dev-qa-db-ja.com

保存せずにupdate_attributesをレールしますか?

レコードを保存しない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'できることを知っています、しかし私はそれらをすべて一行で更新したいです。

359
tybro0103

あなたが探しているものは 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
566
Ajedi32

assign_attributesまたはattributes=を使うことができます(それらは同じです)

更新方法のチートシート(Rails 4用):

  • update_attributes = assign_attributes + save
  • attributes= = assign_attributesのエイリアス
  • update = update_attributesのエイリアス

出典:
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

157
Yarin

'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
63
bruno077

保存せずに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=は、Railsのassign_attributesとわずかに異なります。attributes=は、渡された引数がハッシュであることを確認し、ハッシュでない場合はすぐに戻ります。 assign_attributesには、そのようなハッシュチェックはありません。 attributes=のActiveRecord Attribute Assignment APIドキュメント を参照してください。

次の無効なコードは、属性を設定せずに単純に戻ることにより、暗黙的に失敗します。

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

attributes=は、実際には割り当てられなかった場合でも、割り当てが正常に行われたかのように静かに動作します。

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

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

assign_attributesは、stringify_keysに対してNoMethodError例外を発生させ、最初の引数がハッシュではないことを示します。例外自体は実際の原因についてあまり有益ではありませんが、例外が発生するという事実はvery重要です。

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

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

Rails 3のレッスンは次のとおりです:alwaysassign_attributesの代わりにattributes=を使用します。

Rails 4

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

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を呼び出す前に検証の問題を処理できます。

8
Michael Gaskill