Как я могу установить значения по умолчанию в ActiveRecord? - PullRequest
402 голосов
/ 30 ноября 2008

Как установить значение по умолчанию в ActiveRecord?

Я вижу сообщение от Пратика, которое описывает уродливый, сложный кусок кода: 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

Я видел следующие примеры, которые гуглили вокруг:

  def initialize 
    super
    self.status = ACTIVE unless self.status
  end

и

  def after_initialize 
    return unless new_record?
    self.status = ACTIVE
  end

Я также видел, как люди помещали это в свои миграции, но я бы предпочел, чтобы это было определено в коде модели.

Есть ли канонический способ установить значение по умолчанию для полей в модели ActiveRecord?

Ответы [ 26 ]

0 голосов
/ 17 октября 2010

after_initialize метод устарел, вместо него используйте обратный вызов.

after_initialize :defaults

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
end

однако использование : по умолчанию в ваших миграциях по-прежнему является самым чистым способом.

0 голосов
/ 04 февраля 2011

использовать default_scope в рельсах 3

API DOC

ActiveRecord скрывает разницу между значениями по умолчанию, определенными в базе данных (схема), и значениями по умолчанию, установленными в приложении (модели). Во время инициализации он анализирует схему базы данных и отмечает все значения по умолчанию, указанные там. Позже, при создании объектов, он назначает значения, заданные схемой по умолчанию, не касаясь базы данных.

обсуждение

0 голосов
/ 24 марта 2016

https://github.com/keithrowell/rails_default_value

class Task < ActiveRecord::Base
  default :status => 'active'
end
0 голосов
/ 31 марта 2011

Я обнаружил, что использование метода проверки обеспечивает большой контроль над настройками по умолчанию. Вы даже можете установить значения по умолчанию (или провалить проверку) для обновлений. Вы даже можете установить другое значение по умолчанию для вставок и обновлений, если вы действительно этого хотите. Обратите внимание, что значение по умолчанию не будет установлено до #valid? называется.

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

Относительно определения метода after_initialize могут быть проблемы с производительностью, поскольку after_initialize также вызывается каждым объектом, возвращаемым: find: http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find

0 голосов
/ 31 мая 2012

Из API документов http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html Используйте метод before_validation в вашей модели, он дает вам возможность создания определенной инициализации для вызовов создания и обновления. например в этом примере (снова код взят из примера api docs) поле номера инициализируется для кредитной карты. Вы можете легко адаптировать это, чтобы установить любые значения, которые вы хотите

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

Удивлен, что его здесь не предложили

0 голосов
/ 12 ноября 2013

Если столбец является столбцом типа «состояние», и ваша модель пригодна для использования конечных автоматов, рассмотрите возможность использования aasm gem , после чего вы можете просто выполнить

  aasm column: "status" do
    state :available, initial: true
    state :used
    # transitions
  end

Он по-прежнему не инициализирует значение для несохраненных записей, но он немного чище, чем сворачивание собственного с init или чем-то еще, и вы пожинаете другие преимущества Aasm, такие как области действия для всех ваших статусов.

...