Rails aktualizuje atrybuty bez zapisywania?

Czy istnieje alternatywa dla update_attributes, która nie zapisuje rekordu?

Więc mógłbym zrobić coś takiego:

@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, wiem, że mogę @car.model = 'Sierra', ale chcę zaktualizować je wszystkie na jednej linii.

Author: user2262149, 2011-07-21

4 answers

Wierzę, że to, czego szukasz, to assign_attributes.

Jest to w zasadzie to samo co update_attributes, ale nie zapisuje rekordu:

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
 527
Author: Ajedi32,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-10 16:08:26

Możesz użyć assign_attributes LUB attributes= (są takie same)

Ściągawka metod aktualizacji (dla Rails 4):

  • update_attributes = assign_attributes + save
  • attributes= = alias assign_attributes
  • update = alias update_attributes

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

Kolejny oszust sheet:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet

 140
Author: Yarin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 13:47:16

Możesz użyć metody 'attributes':

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

Źródło: http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Atrybuty = (new_attributes, guard_protected_attributes = true) Pozwala ustawić wszystkie atrybuty na raz, przekazując hash z kluczami pasującymi do nazw atrybutów (które ponownie pasują do nazw kolumn).

Jeśli guard_protected_attributes jest prawdziwe( domyślne), wtedy wrażliwe atrybuty mogą być chronione z tej postaci przypisanie masy przy użyciu makra attr_protected. Można też alternatywnie określić, do których atrybutów można uzyskać dostęp za pomocą makra attr_accessible. Wtedy wszystkie atrybuty nie zawarte w tym nie będą mogły być przypisane masowo.

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
 60
Author: bruno077,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 14:58:24

Do masowego przypisywania wartości do modelu ActiveRecord bez zapisywania, użyj metod assign_attributes lub attributes=. Metody te są dostępne w Rails 3 i nowszych. Jednak istnieją niewielkie różnice i związane z wersją gotchas należy pamiętać.

Obie metody podążają za tym użyciem:

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

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

Zauważ, że żadna z metod nie wykona walidacji ani nie wykona wywołań zwrotnych; wywołanie zwrotne i Walidacja nastąpi po wywołaniu save.

Rails 3

attributes= różni się nieco z assign_attributes w Rails 3. attributes= sprawdzi, czy przekazany do niego argument jest Hashem i zwróci natychmiast, jeśli nim nie jest; assign_attributes nie ma takiego Hash check. Zapoznaj się z dokumentacją API przypisywania atrybutów ActiveRecord attributes=.

Następujący nieprawidłowy kod po cichu zawiedzie, po prostu zwracając bez ustawiania atrybutów:

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

attributes= będzie cicho zachowywać się tak, jakby zadania zostały wykonane pomyślnie, podczas gdy naprawdę, nie były.

To nieprawidłowy kod wywoła wyjątek, gdy assign_attributes spróbuje zsynchronizować klucze hashujące tablicy:

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

assign_attributes wywoła wyjątek NoMethodError dla stringify_keys, wskazując, że pierwszy argument nie jest skrótem. Sam wyjątek nie jest bardzo pouczający o rzeczywistej przyczynie, ale fakt, że wyjątek występuje, jest bardzo ważny.

Jedyną różnicą między tymi przypadkami jest metoda zastosowana do przypisania masy: attributes= po cichu udaje się, a assign_attributes wyświetla wyjątek informujący o wystąpieniu błędu.

Te przykłady mogą wydawać się wymyślone i są do pewnego stopnia, ale ten typ błędu może łatwo wystąpić podczas konwersji danych z API, lub nawet po prostu używając serii transformacji danych i zapominając o Hash[] wynikach końcowego .map. Zachowaj trochę kodu 50 linii powyżej i 3 Funkcje usunięte z przypisania atrybutów, a masz przepis na awarię.

Lekcja z Rails 3 jest taka: zawsze używaj assign_attributes zamiast attributes=.

Rails 4

W Rails 4, attributes= jest po prostu aliasem do assign_attributes. Zapoznaj się z dokumentacją API przypisywania atrybutów ActiveRecord attributes=.

W przypadku Rails 4, każda z metod może być używana zamiennie. Nie podanie Hasha jako pierwszego argumentu spowoduje bardzo pomocny wyjątek: ArgumentError: When assigning attributes, you must pass a hash as an argument.

Walidacje

Jeśli przygotowujesz się do wykonywania zadań przed lotem do save, możesz być interesuje się również walidacją przed zapisem. Możesz do tego użyć metod valid? i invalid?. Obie zwracają wartości logiczne. valid? zwraca true, jeśli niezapisany model przejdzie wszystkie walidacje lub false, jeśli nie. invalid? jest po prostu odwrotnością valid?

valid? Można używać w ten sposób:

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

Daje to możliwość obsługi wszelkich problemów z walidacją przed wywołaniem save.

 6
Author: Michael Gaskill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 15:16:01