Rails: 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 ustawienia domyślnej wartość dla pól w modelu ActiveRecord?

Author: Promise Preston, 2008-11-30

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

  1. 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.
  2. 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.
  3. nadpisywanie initialize może działać, ale nie zapomnij zadzwonić super!
  4. 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?
  5. 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:

  1. 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

  2. Jeśli wybierasz tylko podzbiór kolumn dla modelu (tj. używając select w zapytaniu takim jak Person.select(:firstname, :lastname).all), otrzymasz MissingAttributeError, jeśli twoja metoda init uzyska dostęp do kolumny, która nie została uwzględniona w klauzuli select. 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)

 569
Author: Jeff Perrin,
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

Rails 5+

Możesz użyć metodyatrybutu w swoich modelach, np.:

class Account < ApplicationRecord
  attribute :locale, :string, default: 'en'
end

Można również przekazać lambda do parametru default. Przykład:

attribute :uuid, :string, default: -> { SecureRandom.uuid }

Drugim argumentem jest type i może to być również niestandardowa instancja klasy type, na przykład:

attribute :uuid, UuidType.new, default: -> { SecureRandom.uuid }
 100
Author: Lucas Caton,
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
2020-07-06 06:35:00

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).

 49
Author: Laurent Farcy,
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
 41
Author: Joseph Lord,
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

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
 18
Author: Brad Murray,
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

Chłopaki z Phusion mają do tego jakiś fajny plugin .

 16
Author: Milan Novota,
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.

 8
Author: peterhurford,
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"
 8
Author: aidan,
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
 8
Author: Blair Anderson,
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

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.

Najprostsza rzecz jest często najlepsza. Mniej wiedzy i potencjalnych punktów zamieszania w kodzie. I to "po prostu działa".

class AddStatusToItem < ActiveRecord::Migration
  def change
    add_column :items, :scheduler_type, :string, { null: false, default: "hotseat" }
  end
end

Lub, aby zmienić kolumnę bez tworzenia nowej, wykonaj albo:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column_default :items, :scheduler_type, "hotseat"
  end
end

A może nawet lepiej:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column :items, :scheduler_type, :string, default: "hotseat"
  end
end

Sprawdź oficjalny przewodnik RoR dla opcji zmiany kolumny metody.

null: false wyłącza wartości NULL w DB i, jako dodatkową korzyść, aktualizuje również tak, że wszystkie wcześniej istniejące rekordy DB, które były wcześniej null, są ustawiane z wartością domyślną dla tego pola. Możesz wykluczyć ten parametr w migracji, jeśli chcesz, ale uważam, że jest bardzo przydatny!

W Rails 5 + sposób kanoniczny jest taki, jak powiedział @Lucas Caton:
class Item < ActiveRecord::Base
  attribute :scheduler_type, :string, default: 'hotseat'
end
 5
Author: Magne,
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
2020-05-11 08:48:48

po to są konstruktorzy! Nadpisuje metodę initialize modelu.

Użyj metody after_initialize.

 4
Author: John Topley,
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!
 4
Author: Tony,
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

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
 3
Author: clem,
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

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

 2
Author: Sean,
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

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.
 1
Author: Jeff Gran,
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
class Item < ActiveRecord::Base
  def status
    self[:status] or ACTIVE
  end

  before_save{ self.status ||= ACTIVE }
end
 1
Author: Mike Breen,
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

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 .

 0
Author: skalee,
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.

 0
Author: Greg,
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

 0
Author: Kelvin,
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.

 0
Author: Bad Request,
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
 0
Author: Keith Rowell,
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

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

 0
Author: etipton,
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

Oto rozwiązanie, które wykorzystałem, że byłem trochę zaskoczony, że nie zostało jeszcze dodane.

Są dwie części. Pierwsza część to ustawienie wartości domyślnej w rzeczywistej migracji, a druga część to dodanie walidacji w modelu zapewniającej, że obecność jest prawdziwa.

add_column :teams, :new_team_signature, :string, default: 'Welcome to the Team'

Więc zobaczysz tutaj, że wartość domyślna jest już ustawiona. Teraz w walidacji chcesz upewnić się, że zawsze istnieje wartość dla Ciągu, więc po prostu wykonaj

 validates :new_team_signature, presence: true

To co zrobi to ustawi domyślna wartość dla Ciebie. (dla mnie mam" Welcome to the Team"), a potem pójdzie o krok dalej i zapewni, że zawsze jest wartość obecna dla tego obiektu.

Mam nadzieję, że to pomoże!
 0
Author: kdweber89,
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
2019-02-08 15:47:26
# db/schema.rb
create_table :store_listings, force: true do |t|
  t.string :my_string, default: "original default"
end

StoreListing.new.my_string # => "original default"

# app/models/store_listing.rb
class StoreListing < ActiveRecord::Base
  attribute :my_string, :string, default: "new default"
end

StoreListing.new.my_string # => "new default"

class Product < ActiveRecord::Base
  attribute :my_default_proc, :datetime, default: -> { Time.now }
end

Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
sleep 1
Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600
 0
Author: shilovk,
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
2019-12-15 19:29:55

Miałem podobne wyzwanie podczas pracy nad aplikacją Rails 6.

Oto Jak to rozwiązałem :

Mam Users tabelę i Roles tabelę. Tabela Users należy do tabeli Roles. Mam również modele Admin i Student, które dziedziczą z tabeli Users.

Wymagane było ustawienie domyślnej wartości dla roli za każdym razem, gdy tworzony jest użytkownik, powiedzmy admin rola, która ma id = 1 lub student rola, która ma id = 2.

class User::Admin < User
  before_save :default_values

  def default_values
    # set role_id to '1' except if role_id is not empty
    return self.role_id = '1' unless role_id.nil?
  end
end

Oznacza to że przed utworzeniem/zapisem użytkownika admin w bazie danych, {[16] } jest ustawiane jako domyślne 1, jeśli nie jest puste.

return self.role_id = '1' unless role_id.nil? 

Jest tym samym co:

return self.role_id = '1' unless self.role_id.nil?

I to samo co:

self.role_id = '1' if role_id.nil?
[18]}ale pierwszy jest czystszy i bardziej precyzyjny. To wszystko.

Mam nadzieję, że to pomoże

 0
Author: Promise Preston,
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
2020-06-23 17:54:47

Używam tego od jakiegoś czasu.

# post.rb
class Post < ApplicationRecord
  attribute :country, :string, default: 'ID'
end
 0
Author: Yana Agun Siswanto,
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
2020-10-22 22:26:17

Użyj default_scope w rails 3

Api doc

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.

Dyskusja

 -2
Author: Viktor Trón,
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

 -3
Author: jamesc,
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