Update_attributes kaydetmeden raydan çıkıyor mu?


386

Kaydı kaydetmeyen update_attributes için bir alternatif var mı?

Yani şöyle bir şey yapabilirdim:

@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

BTW, yapabileceğimi biliyorum @car.model = 'Sierra', ama hepsini tek bir satırda güncellemek istiyorum.


ne demek "kaydı kaydetme"?
Anatoly

update_attributes, modeli DB'ye kaydeder. Benzer bir yöntem olup olmadığını merak ediyorum.
tybro0103

3
nitelikleri tahribatsız bir yöntem. Ayrıntılar için API'ya bakın
Anatoly

3
Update_column (name, value) kullanabilirsiniz Bir nesneyi kaydet çağrısı yapmadan tek bir özniteliğini günceller. 1. Doğrulama atlandı. 2. Geri aramalar atlanır. 3. Bu sütun varsa, updated_at / updated_on sütunu güncellenmez. apidock.com/rails/ActiveRecord/Persistence/update_column
Antoine

10
assign_attributes 3.1+
elado

Yanıtlar:


597

Aradığın şeyin olduğuna inanıyorum assign_attributes.

Temel olarak update_attributes ile aynıdır, ancak kaydı kaydetmez:

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

Örneğiniz, bu satırı modelden yapıştırmadığınız için biraz yanıltıcıdır attr_accessible :is_admin, :as => :admin:;)
Robin

@Robin Veya sadece: attr_protected :is_admin. Veya: attr_accessible :nameBu örnekte, is_admin korunmaktadır. Ayrıca, korumalı bir özniteliği toplu olarak atamaya çalışmanın , örnekte gösterilmemesine rağmen, .assign_attributesgerçekten bir artış ActiveModel::MassAssignmentSecurity::Errorsağladığını da not etmeliyim.
Ajedi32

Evet ama benim çizgim bağlandığın doktora ait. Sadece tüm örneği kopyalamanız / yapıştırmanız gerektiğini söylüyorum. Ama evet, sadece korunduğunu söyleyebilirsiniz.
Robin

@Robin Örneği biraz daha spesifik olacak şekilde güncelleyeceğim. Dokümanlardaki örnek de user.assign_attributes({ :name => 'Josh', :is_admin => true })bir hata mesajı verdiğinden ve aslında kullanıcının name özelliğini ayarlamadığından bahsetmediği için biraz yanıltıcıdır .
Ajedi32

7
assign_attributes, Rails 3.1'den itibaren kullanılabilir, bu nedenle hala Rails'in eski bir sürümünü çalıştırıyorsanız kullanamazsınız.
Haegin

174

Sen kullanabilirsiniz assign_attributesveyaattributes= (aynılar)

Güncelleme yöntemleri hile sayfası (Rails 6 için):

  • update= assign_attributes+save
  • attributes= = takma adı assign_attributes
  • update_attributes = kullanımdan kaldırıldı, takma adı update

Kaynak:
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

Başka bir hile sayfası:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet


1
Açık ve kısa. Teşekkürler.
freemanoid

1
.attributes = val durumunda, modelinizde başka bir model için_bir varsa ve bu_seçiliğini_ kabul ederse, o_model_attributes (kimliği olmayan) iletilirse, devam etmeseniz bile mevcut has_one modeli silinir (örn. kaydet). Ancak assign_attributes böyle davranmaz.
ClassyPimp

65

'Attributes' yöntemini kullanabilirsiniz:

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

Kaynak: http://api.rubyonrails.org/classes/ActiveRecord/Base.html

attributes = (new_attributes, guard_protected_attributes = true) Öznitelik adlarıyla eşleşen anahtarları (yine sütun adlarıyla eşleşir) içeren bir karma ileterek bir kerede tüm öznitelikleri ayarlamanıza olanak tanır .

Guard_protected_attributes doğruysa (varsayılan), hassas öznitelikler attr_protected makrosu kullanılarak bu toplu atama biçiminden korunabilir. Alternatif olarak, attr_accessible makrosuyla hangi özelliklere erişilebileceğini belirleyebilirsiniz. Bu durumda, buna dahil olmayan tüm özelliklerin toplu olarak atanmasına izin verilmez.

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

Kaydetmeden bir ActiveRecord modeline değerlerin toplu olarak atanması için assign_attributesveyaattributes= yöntemlerinden . Bu yöntemler Rails 3 ve daha yeni sürümlerde mevcuttur. Ancak, farkında olmak için ufak farklılıklar ve versiyonla ilgili gotcha'lar vardır.

Her iki yöntem de bu kullanımı izler:

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

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

Her iki yöntemin de doğrulama yapmayacağını veya geri çağrı yapmayacağını unutmayın; Geri aramalar ve doğrulama,save çağrıldığında gerçekleşir.

Raylar 3

attributes=assign_attributesRails 3'ten biraz farklıdır . Kendisine attributes=iletilen argümanın Karma olup olmadığını kontrol eder ve değilse hemen döner; assign_attributesböyle bir Hash kontrolü yok. İçin ActiveRecord Özellik Atama API'sı belgelerine bakınattributes= .

Aşağıdaki geçersiz kod, öznitelikleri ayarlamadan geri dönerek sessizce başarısız olacaktır:

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

attributes= ödevler başarılı bir şekilde yapılmış gibi sessizce davranacaklar, gerçekten değillerdi.

assign_attributesEkleyen dizinin karma anahtarlarını dizginlemeye çalıştığında bu geçersiz kod bir istisna oluşturur:

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

assign_attributes, ilk argümanın Karma olmadığını belirten bir NoMethodErroristisna oluşturur stringify_keys. İstisnanın kendisi gerçek neden hakkında çok bilgilendirici değildir, ancak bir istisnanın gerçekleşmesi gerçeği çok önemlidir.

Bu durumlar arasındaki tek fark, toplu atama için kullanılan yöntemdir: attributes=sessizce başarılı olur ve assign_attributesbir hata oluştuğunu bildirmek için bir istisna oluşturur.

Bu örnekler tutarlı görünebilir ve bir dereceye kadar olabilirler, ancak bu tür bir hata bir API'dan veri dönüştürülürken veya hatta sadece bir dizi veri dönüşümü kullanılırken ve Hash[]finalin sonuçlarını unuturken kolayca ortaya çıkabilir .map. Bazı kodları 50 satır yukarıda tutun ve öznitelik atamanızdan 3 işlev kaldırıldı ve başarısızlık için bir reçeteniz var.

Raylar 3 ile ders şudur: her zaman kullanmak assign_attributesyerineattributes= .

Raylar 4

Rails 4, attributes=sadece bir takma addır assign_attributes. İçin ActiveRecord Özellik Atama API'sı belgelerine bakınattributes= .

Rails 4 ile, her iki yöntem de birbirinin yerine kullanılabilir. İlk argüman olarak bir Hash'i geçememek çok yararlı bir istisna ile sonuçlanır:ArgumentError: When assigning attributes, you must pass a hash as an argument.

Doğrulamaları

A'ya hazırlanırken ödevleri önceden yayınlıyorsanız save, kaydetmeden önce de doğrulamak isteyebilirsiniz. Bunun için valid?ve invalid?yöntemlerini kullanabilirsiniz . Her ikisi de boole değerlerini döndürür. valid?kaydedilmemiş model tüm doğrulamaları geçerse true değerini, değilse false değerini döndürür. invalid?basitçe tersidirvalid?

valid? şu şekilde kullanılabilir:

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

Bu, aramadan önce herhangi bir doğrulama sorununu ele alma olanağı verecektir save.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.