Jak ustawić domyślne wartości w ActiveRecord?
Jak ustawić wartość domyślną w ActiveRecord?
Widzę post od Pratika, który opisuje brzydki, skomplikowany fragment kodu: http://m.onkey.org/2007/7/24/how-to-set-default-values-in-your-model
class Item < ActiveRecord::Base
def initialize_with_defaults(attrs = nil, &block)
initialize_without_defaults(attrs) do
setter = lambda { |key, value| self.send("#{key.to_s}=", value) unless
!attrs.nil? && attrs.keys.map(&:to_s).include?(key.to_s) }
setter.call('scheduler_type', 'hotseat')
yield self if block_given?
end
end
alias_method_chain :initialize, :defaults
end
Widziałem następujące przykłady googlowania:
def initialize
super
self.status = ACTIVE unless self.status
end
I
def after_initialize
return unless new_record?
self.status = ACTIVE
end
Widziałem też, jak ludzie umieszczają go w swojej migracji, ale wolałbym, aby został zdefiniowany w kodzie modelu.
Czy istnieje kanoniczny sposób ustawiania wartości domyślnej dla pól w Model ActiveRecord?
25 answers
Istnieje kilka problemów z każdą z dostępnych metod, ale uważam, że zdefiniowanie wywołania zwrotnego after_initialize
jest sposobem na przejście z następujących powodów:
-
default_scope
zainicjalizuje wartości dla nowych modeli, ale wtedy będzie to Zakres, na którym znajduje się model. Jeśli po prostu chcesz zainicjalizować niektóre liczby na 0, to jest to , a nie to, czego chcesz. - Definiowanie domyślnych wartości w migracji również działa przez pewien czas... Jak już wspomniano to czy Nie będzie działać, gdy tylko wywołasz Model.nowy.
- nadpisywanie
initialize
może działać, ale nie zapomnij zadzwonićsuper
! - używanie wtyczki takiej jak phusion ' s staje się nieco śmieszne. To jest ruby, czy naprawdę potrzebujemy wtyczki, aby zainicjować niektóre wartości domyślne?
- Overriding
after_initialize
jest przestarzałe od Rails 3. Kiedy nadpisujęafter_initialize
w rails 3.0.3 otrzymuję następujące ostrzeżenie w konsoli:
OSTRZEŻENIE O DEPRECJACJI: Base # after_initialize został wycofany, Proszę użyć Base.zamiast tego metoda after_initialize:. (wywołane z /Users / me / myapp / app / models / my_model:15)
Dlatego powiedziałbym napisać wywołanie zwrotne after_initialize
, które pozwala na domyślne atrybuty oprócz pozwalając ustawić domyślne skojarzenia w taki sposób:
class Person < ActiveRecord::Base
has_one :address
after_initialize :init
def init
self.number ||= 0.0 #will set the default value only if it's nil
self.address ||= build_address #let's you set a default association
end
end
Teraz masz tylko jedno miejsce , aby szukać inicjalizacji swoich Modeli. Używam tej metody, dopóki ktoś nie wymyśli lepszego jeden.
Zastrzeżenia:
-
Dla pól logicznych do:
self.bool_field = true if self.bool_field.nil?
Zobacz komentarz Paula Russella do tej odpowiedzi po więcej szczegółów
-
Jeśli wybierasz tylko podzbiór kolumn dla modelu (tj. używając
select
w zapytaniu takim jakPerson.select(:firstname, :lastname).all
), otrzymaszMissingAttributeError
, jeśli twoja metodainit
uzyska dostęp do kolumny, która nie została uwzględniona w klauzuliselect
. Można się przed tym uchronić w ten sposób:self.number ||= 0.0 if self.has_attribute? :number
I dla boolean kolumna...
self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?
Zauważ również, że składnia jest inna przed Rails 3.2 (zobacz komentarz Cliffa Darlinga poniżej)
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-07-11 02:14:21
Wprowadzamy wartości domyślne do bazy danych poprzez migracje (poprzez podanie opcji :default
w definicji każdej kolumny) i pozwalamy Active Record używać tych wartości do ustawiania wartości domyślnych dla każdego atrybutu.
IMHO, to podejście jest zgodne z zasadami AR: convention over configuration, DRY, definicja tabeli napędza model, a nie na odwrót.
Zauważ, że domyślne wartości są nadal w kodzie aplikacji (Ruby), choć nie w modelu, ale w migracja (s).
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
2008-11-30 13:45:52
Niektóre proste przypadki mogą być obsługiwane przez zdefiniowanie domyślnej wartości w schemacie bazy danych, ale to nie obsługuje wielu trudniejszych przypadków, w tym obliczonych wartości i kluczy innych modeli. W takich przypadkach robię to:
after_initialize :defaults
def defaults
unless persisted?
self.extras||={}
self.other_stuff||="This stuff"
self.assoc = [OtherModel.find_by_name('special')]
end
end
Zdecydowałem się użyć after_initialize, ale nie chcę, aby było stosowane do obiektów, które znajdują się tylko te nowe lub utworzone. Myślę, że to prawie szokujące, że wywołanie zwrotne after_new nie jest przewidziane dla tego oczywistego przypadku użycia, ale zrobiłem to, potwierdzając czy obiekt jest już utrzymany, wskazując, że nie jest nowy.
Po obejrzeniu odpowiedzi Brada Murraya jest to jeszcze czystsze, jeśli warunek zostanie przeniesiony na żądanie wywołania zwrotnego:
after_initialize :defaults, unless: :persisted?
# ":if => :new_record?" is equivalent in this context
def defaults
self.extras||={}
self.other_stuff||="This stuff"
self.assoc = [OtherModel.find_by_name('special')]
end
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-05-28 15:05:36
W Rails 5+ możesz użyć metody atrybutu w swoich modelach, np.:
class Account < ApplicationRecord
attribute :locale, :string, default: 'en'
end
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-04-19 01:40:29
Wzorzec wywołania zwrotnego after_initialize można poprawić, wykonując następujące czynności
after_initialize :some_method_goes_here, :if => :new_record?
Ma to niebanalną korzyść, jeśli twój kod init musi radzić sobie z asocjacjami, ponieważ poniższy kod wyzwala subtelne n+1, jeśli przeczytasz początkowy rekord bez włączania skojarzonego.
class Account
has_one :config
after_initialize :init_config
def init_config
self.config ||= build_config
end
end
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
2012-09-14 05:37:50
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
2008-11-30 09:42:56
Jeszcze lepszym / czystszym potencjalnym sposobem niż proponowane odpowiedzi jest nadpisanie accesora, jak to:
def status
self['status'] || ACTIVE
end
Zobacz "nadpisywanie domyślnych accesorów" w dokumentacji ActiveRecord::Basei Więcej informacji ze StackOverflow na temat używania self.
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-23 12:26:37
Używam attribute-defaults
gem
Z dokumentacji:
uruchom sudo gem install attribute-defaults
i dodaj require 'attribute_defaults'
do swojej aplikacji.
class Foo < ActiveRecord::Base
attr_default :age, 18
attr_default :last_seen do
Time.now
end
end
Foo.new() # => age: 18, last_seen => "2014-10-17 09:44:27"
Foo.new(:age => 25) # => age: 25, last_seen => "2014-10-17 09:44:28"
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
2014-10-16 22:46:39
Podobne pytania, ale wszystkie mają nieco inny kontekst: - Jak utworzyć domyślną wartość atrybutów w modelu Rails activerecord?
Najlepsza odpowiedź: zależy, czego chcesz!
jeśli chcesz, aby każdy obiekt zacznij od wartości: użyj after_initialize :init
Chcesz, aby Formularz new.html
miał domyślną wartość po otwarciu strony? use https://stackoverflow.com/a/5127684/1536309
class Person < ActiveRecord::Base
has_one :address
after_initialize :init
def init
self.number ||= 0.0 #will set the default value only if it's nil
self.address ||= build_address #let's you set a default association
end
...
end
jeśli chcesz każdy obiekt do mieć wartość obliczoną na podstawie danych wejściowych użytkownika: use before_save :default_values
Chcesz, aby użytkownik wprowadził X
, a następnie Y = X+'foo'
? użycie:
class Task < ActiveRecord::Base
before_save :default_values
def default_values
self.status ||= 'P'
end
end
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-23 12:10:47
po to są konstruktorzy! Nadpisuje metodę initialize
modelu.
Użyj metody after_initialize
.
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
2009-11-13 09:56:19
Sup chłopaki, skończyłem robiąc co następuje:
def after_initialize
self.extras||={}
self.other_stuff||="This stuff"
end
Działa jak czar!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
2010-07-27 06:36:21
Po pierwsze: nie zgadzam się z odpowiedzią Jeffa. Ma to sens, gdy aplikacja jest mała, a logika prosta. Jestem tutaj, aby dać wgląd w to, jak może to być problem podczas budowania i utrzymywania większej aplikacji. Nie polecam używać tego podejścia najpierw przy budowaniu czegoś małego, ale aby mieć to na uwadze jako alternatywne podejście: {]}
Pytanie brzmi, czy ta wartość domyślna dla rekordów jest logiką biznesową. Jeśli tak, byłbym ostrożny, mówiąc to w modelu ORM. Ponieważ pole o którym wspomina ryw jest aktywne , brzmi to jak logika biznesowa. Np. użytkownik jest aktywny.
Dlaczego miałbym być ostrożny, aby umieścić obawy Biznesowe w modelu ORM?
Łamie SRP. Każda klasa dziedzicząca z ActiveRecord:: Base wykonuje już lot różnych rzeczy, wśród nich są spójność danych (walidacje) i trwałość (save). Wprowadzenie logiki biznesowej, bez względu na to, czy jest mała, w Ar:: Base łamie SRP.
Testowanie jest wolniejsze. Jeśli chcę przetestować jakąkolwiek formę logiki występującą w moim modelu ORM, moje testy muszą zainicjować Rails, aby uruchomić. Nie będzie to zbyt dużym problemem na początku aplikacji, ale będzie się gromadzić, dopóki testy jednostkowe nie potrwają długo.
To złamie SRP jeszcze bardziej w dół linii, i na konkretne sposoby. Powiedzmy, że nasza firma wymaga od nas wysyłania e-maili do użytkowników, gdy pozycja stanie się aktywna? Teraz dodajemy e-mail logic do modelu Item ORM, którego głównym zadaniem jest modelowanie przedmiotu. Nie powinno dbać o logikę poczty e-mail. Jest to przypadek biznesowych skutków ubocznych . Nie należą one do modelu ORM.
Trudno jest dywersyfikować. Widziałem Dojrzałe aplikacje Rails z takimi rzeczami jak Pole init_type: string wspierane przez bazę danych, których jedynym celem jest kontrolowanie logiki inicjalizacji. Powoduje to zanieczyszczenie bazy danych w celu rozwiązania problemu strukturalnego. Są lepsze sposoby. uwierz.
Sposób PORO: chociaż jest to nieco więcej kodu, pozwala zachować modele ORM i logikę biznesową osobno. Kod tutaj jest uproszczony, ale powinien pokazywać ideę:
class SellableItemFactory
def self.new(attributes = {})
record = Item.new(attributes)
record.active = true if record.active.nil?
record
end
end
Wtedy, gdy jest to na miejscu, sposobem na utworzenie nowego elementu będzie
SellableItemFactory.new
I moje testy mogły teraz po prostu sprawdzić, czy ItemFactory ustawia aktywny element, jeśli nie ma wartości. Brak konieczności inicjalizacji szyn, brak łamania SRP. Gdy inicjalizacja elementu staje się bardziej zaawansowane (np. ustaw pole statusu, Typ domyślny, itp.) ItemFactory może to dodać. Jeśli skończymy z dwoma typami domyślnych, możemy utworzyć nowy BusinesCaseItemFactory, aby to zrobić.
Uwaga: korzystne może być również użycie dependency injection tutaj, aby umożliwić fabryce zbudowanie wielu aktywnych rzeczy, ale pominąłem to dla uproszczenia. Oto ona: jaźń.new (klass = pozycja, atrybuty = {})
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-07-27 09:40:57
Odpowiedź jest od dawna, ale często potrzebuję wartości domyślnych i wolę nie umieszczać ich w bazie danych. Tworzę DefaultValues
:
module DefaultValues
extend ActiveSupport::Concern
class_methods do
def defaults(attr, to: nil, on: :initialize)
method_name = "set_default_#{attr}"
send "after_#{on}", method_name.to_sym
define_method(method_name) do
if send(attr)
send(attr)
else
value = to.is_a?(Proc) ? to.call : to
send("#{attr}=", value)
end
end
private method_name
end
end
end
A potem używaj go w moich modelach w ten sposób:
class Widget < ApplicationRecord
include DefaultValues
defaults :category, to: 'uncategorized'
defaults :token, to: -> { SecureRandom.uuid }
end
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-02-14 21:35:41
Widziałem też, jak ludzie umieszczają to w swoich migracjach, ale wolałbym to zobaczyć zdefiniowany w kodzie modelu.
Czy istnieje kanoniczny sposób ustawiania wartości domyślnej dla pól w Model ActiveRecord?
Sposobem kanonicznym Rails, przed Rails 5, było ustawienie go w migracji i po prostu zajrzyj do db/schema.rb
, Gdy chcesz zobaczyć, jakie domyślne wartości są ustawiane przez DB dla dowolnego modelu.
Wbrew temu, co stwierdza odpowiedź @Jeff Perrin (co jest nieco stare), podejście migracyjne zastosuje nawet domyślne przy użyciu Model.new
, ze względu na magię Rails. Sprawdzona praca w Rails 4.1.16.
class AddStatusToItem < ActiveRecord::Migration
def change
add_column :items, :scheduler_type, :string, { null: false, default: "hotseat" }
end
end
null: false
wyłącza wartości NULL w DB i, jako dodatkową korzyść, aktualizuje również wszystkie wcześniej istniejące rekordy DB, które są ustawione z wartością domyślną dla tego pola. Możesz wykluczyć ten parametr w migracja, jeśli chcesz, ale uważam, że to bardzo przydatne!
class Item < ActiveRecord::Base
attribute :scheduler_type, :string, default: 'hotseat'
end
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-22 14:46:34
Problem z rozwiązaniami after_initialize polega na tym, że musisz dodać after_initialize do każdego obiektu, który wyszukujesz poza DB, niezależnie od tego, czy masz dostęp do tego atrybutu, czy nie. Proponuję leniwe podejście.
Metody atrybutów (gettery) są oczywiście same w sobie, więc można je nadpisać i podać domyślne. Coś w stylu:
Class Foo < ActiveRecord::Base
# has a DB column/field atttribute called 'status'
def status
(val = read_attribute(:status)).nil? ? 'ACTIVE' : val
end
end
Chyba, że, jak ktoś wskazał, musisz zrobić Foo.find_by_status ('aktywny'). W takim razie myślę, że naprawdę musisz ustawić domyślne ograniczenia w swojej bazie danych, jeśli DB obsługuje to.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
2012-09-08 00:43:17
Napotkałem problemy z after_initialize
podawaniem błędów ActiveModel::MissingAttributeError
przy wykonywaniu skomplikowanych znalezisk:
Eg:
@bottles = Bottle.includes(:supplier, :substance).where(search).order("suppliers.name ASC").paginate(:page => page_no)
"szukaj" w .where
to hash warunków
Więc skończyło się na tym, że zrobiłem to przez nadpisanie initialize w ten sposób:
def initialize
super
default_values
end
private
def default_values
self.date_received ||= Date.current
end
Wywołanie super
jest konieczne, aby upewnić się, że obiekt inicjalizuje się poprawnie z ActiveRecord::Base
przed wykonaniem mojego niestandardowego kodu, czyli: default_values
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
2012-11-30 03:24:52
class Item < ActiveRecord::Base
def status
self[:status] or ACTIVE
end
before_save{ self.status ||= ACTIVE }
end
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
2013-07-15 07:59:14
Zdecydowanie sugeruję użycie klejnotu "default_value_for": https://github.com/FooBarWidget/default_value_for
Istnieje kilka trudnych scenariuszy, które wymagają nadpisania metody initialize, co robi ten gem.
Przykłady:
Domyślną wartością db jest NULL, domyślną wartością zdefiniowaną przez model/ruby jest "jakiś łańcuch", ale w rzeczywistości chcesz ustawić wartość na nil z dowolnego powodu: MyModel.new(my_attr: nil)
Większość rozwiązań tutaj nie ustawia wartości na nil, a zamiast tego ustawi ją na domyślną.
Ok, więc zamiast podejść ||=
, przełącz się na my_attr_changed?
...
Ale wyobraź sobie, że domyślną wartością db jest "some string", domyślną wartością zdefiniowaną przez model/ruby jest "some other string", ale w określonym scenariuszu, chcesz ustawić wartość na" some string " (domyślna wartość db): MyModel.new(my_attr: 'some_string')
Spowoduje to, że my_attr_changed?
będzie false , ponieważ wartość odpowiada wartości domyślnej db, która z kolei odpali Twoje domyślny kod zdefiniowany przez ruby i ustaw wartość na "jakiś inny ciąg" -- ponownie, nie to, co chciałeś.
Z tych powodów nie wydaje mi się, aby można było to osiągnąć za pomocą haka after_initialize.
Ponownie myślę, że klejnot "default_value_for" przyjmuje właściwe podejście: https://github.com/FooBarWidget/default_value_for
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-08-20 04:35:02
Chociaż robienie tego przy ustawianiu wartości domyślnych jest w większości przypadków mylące i niewygodne, możesz również użyć :default_scope
. Zobacz komentarz squila tutaj .
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
2010-07-21 12:57:32
Metoda After_initialize jest przestarzała, zamiast tego użyj funkcji zwrotnej.
after_initialize :defaults
def defaults
self.extras||={}
self.other_stuff||="This stuff"
end
Jednak użycie : default w Twoich migracjach jest nadal najczystszym sposobem.
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
2010-10-17 01:59:13
Odkryłem, że użycie metody walidacji zapewnia dużą kontrolę nad ustawieniami domyślnymi. Możesz nawet ustawić domyślne wartości (lub nieudaną walidację) dla aktualizacji. Możesz nawet ustawić inną wartość domyślną dla wstawek i aktualizacji, jeśli naprawdę chcesz. Zauważ, że wartość domyślna nie będzie ustawiona do #valid? nazywa się.
class MyModel
validate :init_defaults
private
def init_defaults
if new_record?
self.some_int ||= 1
elsif some_int.nil?
errors.add(:some_int, "can't be blank on update")
end
end
end
Jeśli chodzi o definiowanie metody after_initialize, mogą wystąpić problemy z wydajnością, ponieważ after_initialize jest również wywoływany przez każdy obiekt zwracany przez: find : http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find
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
2011-03-30 21:24:23
Jeśli kolumna stanie się kolumną typu "status", a twój model nadaje się do użycia maszyn stanowych, rozważ użycie AASM gem , po czym możesz po prostu zrobić
aasm column: "status" do
state :available, initial: true
state :used
# transitions
end
Nadal nie inicjalizuje wartości dla niezapisanych rekordów, ale jest nieco czystsza niż nagrywanie własnych z init
czy cokolwiek innego, a Ty czerpiesz inne korzyści z aasm, takie jak zakresy dla wszystkich swoich statusów.
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
2013-11-11 22:30:44
Https://github.com/keithrowell/rails_default_value
class Task < ActiveRecord::Base
default :status => 'active'
end
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-03-24 12:39:31
Użyj default_scope w rails 3
ActiveRecord zasłania różnicę między domyślnym zdefiniowaniem w bazie danych (schemacie) a domyślnym wykonaniem w aplikacji (modelu). Podczas inicjalizacji, analizuje schemat bazy danych i notuje wszelkie wartości domyślne określone tam. Później, podczas tworzenia obiektów, przypisuje te wartości domyślne określone w schemacie bez dotykania bazy danych.
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-23 12:34:45
Z dokumentów api http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Użyj metody before_validation
w swoim modelu, daje ona opcje tworzenia konkretnych inicjalizacji dla wywołań tworzenia i aktualizacji
np. w tym przykładzie (ponownie kod zaczerpnięty z przykładu api docs) pole numer jest inicjalizowane dla karty kredytowej. Możesz łatwo dostosować to, aby ustawić dowolne wartości
class CreditCard < ActiveRecord::Base
# Strip everything but digits, so the user can specify "555 234 34" or
# "5552-3434" or both will mean "55523434"
before_validation(:on => :create) do
self.number = number.gsub(%r[^0-9]/, "") if attribute_present?("number")
end
end
class Subscription < ActiveRecord::Base
before_create :record_signup
private
def record_signup
self.signed_up_on = Date.today
end
end
class Firm < ActiveRecord::Base
# Destroys the associated clients and people when the firm is destroyed
before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
end
Zaskoczony, że jego nie został tu zasugerowany
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
2012-05-31 18:43:21