ActiveRecord에서 기본값을 어떻게 설정합니까?


417

ActiveRecord에서 기본값을 어떻게 설정합니까?

나는 추악하고 복잡한 코드 덩어리를 설명하는 Pratik의 게시물을 참조하십시오 : 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 모델에서 필드의 기본값을 설정하는 정식 방법이 있습니까?


두 가지 변형으로 질문에 직접 답변 한 것 같습니다 :)
Adam Byrtek

19
참고 인의 "표준"루비 관용구 'self.status하지 않는 한 self.status가 ACTIVE ='고 'self.status || = ACTIVE'
마이크 우드 하우스

1
Jeff Perrin의 답변은 현재 승인 된 것으로 표시된 답변보다 훨씬 낫습니다. default_scope는 기본값을 설정하는 데 사용할 수없는 솔루션입니다. 쿼리 동작도 변경하는 데 큰 영향을 미치기 때문입니다.
로렌스


2
이 질문에 대한 모든 upvotes 주어, 나는 루비는 액티브위한 setDefaultValue 방법을 필요로 말할 것
spartikus

답변:


557

사용 가능한 각 방법에는 몇 가지 문제가 있지만 after_initialize콜백 을 정의 하면 다음과 같은 이유로 갈 수 있습니다.

  1. default_scope새 모델의 값을 초기화하지만 모델을 찾는 범위가됩니다. 일부 숫자를 0으로 초기화 하려면 원하는 것이 아닙니다 .
  2. 마이그레이션에서 기본값을 정의하는 것도 시간의 일부로 작동합니다. 이미 언급했듯이 Model.new를 호출하면 작동 하지 않습니다 .
  3. 재정의 initialize는 효과가 있지만 전화하는 것을 잊지 마십시오 super!
  4. phusion과 같은 플러그인을 사용하는 것은 약간 어리 석습니다. 이것은 루비입니다. 기본값을 초기화하기 위해 플러그인이 정말로 필요합니까?
  5. Rails 3에서는 재정의 after_initialize 가 더 이상 사용되지 않습니다. Rails after_initialize3.0.3에서 재정의 하면 콘솔에 다음 경고가 표시됩니다.

DEPRECATION 경고 : Base # after_initialize가 사용되지 않으므로 대신 Base.after_initialize : method를 사용하십시오. (/ Users / me / myapp / app / models / my_model : 15에서 호출)

따라서 after_initialize콜백을 작성하면 다음 과 같이 연결에서 기본값을 설정할 수 있을뿐만 아니라 기본 속성 을 사용할 수 있습니다.

  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    

이제 모델의 초기화를 찾을 수있는 곳이 뿐입니다 . 누군가가 더 나은 방법을 찾을 때 까지이 방법을 사용하고 있습니다.

주의 사항 :

  1. 부울 필드의 경우 다음을 수행하십시오.

    self.bool_field = true if self.bool_field.nil?

    자세한 내용은이 답변에 대한 Paul Russell의 의견을 참조하십시오.

  2. 모델에 대한 열의 하위 집합 만 선택하는 경우 (예 : select와 같은 쿼리에서 사용 Person.select(:firstname, :lastname).all) 메서드가 절 에 포함되지 않은 열에 액세스하는 MissingAttributeError경우 얻을 수 있습니다. 다음과 같이이 경우를 막을 수 있습니다.initselect

    self.number ||= 0.0 if self.has_attribute? :number

    부울 열의 경우 ...

    self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?

    또한 구문은 Rails 3.2 이전과 다릅니다 (아래 Cliff Darling의 의견 참조).


7
이것은 분명히 이것을 달성하는 가장 좋은 방법으로 보입니다. 정말 이상하고 불행합니다. 생성시 모델 속성 기본값을 설정하는 바람직한 방법은 Rails가 이미 내장해야했던 것처럼 보입니다. 재정의하는 다른 (신뢰할 수있는) 다른 방법 initialize은 명확하고 명확하게 정의해야하는 방식으로 실제로 복잡해 보입니다. 이 기능이 이미 어딘가에 있다고 생각하고 알지 못했기 때문에 검색하기 전에 문서를 크롤링하는 데 몇 시간을 보냈습니다.
seaneshbaugh

106
이것에 대한 한 가지 참고 사항-기본값으로 설정하려는 부울 필드가있는 self.bool_field ||= true경우 명시 적으로 false로 초기화하더라도 필드를 true로 설정하므로 수행하지 마십시오 . 대신 self.bool_field = true if self.bool_field.nil?.
Paul Russell

2
포인트 # 2와 관련하여 Model.new는 실제로 마이그레이션에 정의 된 기본값 또는 더 정확하게는 테이블 열의 기본값과 함께 작동합니다 (나만?). 그러나 after_initialize 콜백을 기반으로 한 Jeff의 방법이 최선의 방법 일 것입니다. 그냥 질문 : 더럽지 만 저장되지 않은 객체와 함께 작동합니까? 귀하의 예에서 Person.new.number_was는 0.0을 반환합니까?
Laurent Farcy

21
이 방법을 사용할 때는 활성 레코드가있는 특정 열을 선택해야합니다. 이 경우 쿼리에 지정된 속성 만 객체에서 찾을 수 있으며 초기화 코드는를 발생 MissingAttributeError시킵니다. 다음과 같이 추가 검사를 추가 할 수 있습니다 . self.number ||= 0.0 if self.has_attribute? :number 부울 : self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?. 이것은 Rails 3.2 이상이며, 이전에는을 사용 self.attributes.has_key?하고 기호 대신 문자열이 필요합니다.
Cliff Darling

6
연결과 함께이 작업을 수행하면 해당 연결을 조회 할 때 간절히로드됩니다. 시작 initializereturn if !new_record?성능 문제를 방지 할 수 있습니다.
Kyle Macey

68

레일 5+

모델 내 에서 속성 방법을 사용할 수 있습니다 ( 예 :

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

default매개 변수에 람다를 전달할 수도 있습니다 . 예:

attribute :uuid, UuidType.new, default: -> { SecureRandom.uuid }

3
ahhhhh 이것은 내가 찾고 있던 보석입니다! 기본값은 proc도 취할 수 있습니다. 예 : 기본값 :-> {Time.current.to_date}
schpet

1
유형을 두 번째 인수로 지정하십시오. 그렇지 않으면 유형이 지정되고 유형 Value변환이 수행되지 않습니다.
null

기쁘게도 이것은 store_accessor 와도 작동합니다. 예를 들어 store_accessor :my_jsonb_column, :locale다음과 같이 정의 할 수 있습니다.attribute :locale, :string, default: 'en'
Ryan Romanchuk

오, 환상적입니다. 폼으로 표시하기 위해 기본값이 필요했고 이것은 훌륭하게 작동합니다. 고마워 Lucas.
Paul Watson

여전히으로 설정할 수 있습니다 nil. 그들이 nilDB not null+ DB 기본값이 될 수 없다면 + github.com/sshaw/keep_defaults 는 내 경험에서 벗어날 수있는 방법입니다
sshaw

47

마이그레이션을 통해 데이터베이스에 기본값을 넣습니다 ( :default각 열 정의에 옵션을 에 기본값을 설정하고 Active Record에서 이러한 값을 사용하여 각 속성에 대한 기본값을 설정하도록합니다.

IMHO,이 접근법은 AR의 원칙과 일치합니다 : 컨벤션에 대한 컨벤션, DRY, 테이블 정의는 다른 방식이 아니라 모델을 주도합니다.

모델이 아니라 마이그레이션에서는 기본값이 여전히 애플리케이션 (Ruby) 코드에 있습니다.


3
다른 문제는 외래 키의 기본값을 원할 때입니다. 다른 DB에서는 ID가 다를 수 있으므로 외래 키 필드에 ID 값을 하드 코딩 할 수 없습니다.
shmichael

2
그러나 또 다른 문제점은이 방법으로 비 지속적 접근자를 초기화 할 수 없다는 것입니다 (db 열이 아닌 속성).
Viktor Trón

2
또 다른 문제는 한 곳에서 모든 기본값을 반드시 볼 수는 없다는 것입니다. 다른 마이그레이션을 통해 흩어질 수 있습니다.
declan

8
declan, db / schema.rb가 있습니다
Benjamin Atkin

6
나는 미래의 독자들에게 언급하고 싶습니다. 적어도 내가 읽은 내용에서 이것은 AR의 원칙과 상반됩니다. 모델의 논리는 모델 클래스 내에 있어야하며 데이터베이스는 가능한 한 무지해야합니다. 나에게 기본값은 모델에 대한 특정 논리를 구성합니다.
darethas

40

데이터베이스 스키마에서 기본값을 정의하여 일부 간단한 경우를 처리 할 수 ​​있지만 계산 된 값과 다른 모델의 키를 포함하여 여러 까다로운 경우는 처리하지 않습니다. 이 경우 나는 이것을한다 :

after_initialize :defaults

def defaults
   unless persisted?
    self.extras||={}
    self.other_stuff||="This stuff"
    self.assoc = [OtherModel.find_by_name('special')]
  end
end

after_initialize를 사용하기로 결정했지만 새로운 객체 또는 생성 된 객체에만 적용되는 것을 원하지 않습니다. after_new 콜백 이이 명백한 유스 케이스에 제공되지 않는 것이 거의 충격적이지만 객체가 이미 지속되어 객체가 새로운 것이 아님을 확인하여 확인했습니다.

Brad Murray의 답변을 본 후 조건이 콜백 요청으로 이동하면 더 깨끗합니다.

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

4
이것은 정말 중요한 포인트입니다. 대부분의 경우 레코드의 기본값을 설정하면 지속 레코드를로드 할 때가 아니라 새 레코드를 유지하기 전에 만 수행해야한다고 상상해야합니다.
Russell Silva

Thx 친구, 당신은 내 하루를 구했습니다.
stephanfriedrich

2
어때요 :before_create?
Franklin Yu

: before_create는 별도의 새 호출과 저장 호출을 어떻게 처리합니까? 확인하고 전환하기 전에 이해하고 싶습니다.
Joseph Lord

17

after_initialize 콜백 패턴은 다음을 수행하여 간단히 개선 할 수 있습니다.

after_initialize :some_method_goes_here, :if => :new_record?

다음 코드는 관련 코드를 포함하지 않고 초기 레코드를 읽는 경우 미묘한 n + 1을 트리거하기 때문에 초기화 코드가 연관을 처리해야하는 경우 이는 사소한 이점이 있습니다.

class Account

  has_one :config
  after_initialize :init_config

  def init_config
    self.config ||= build_config
  end

end

16

Phusion 녀석은 이것에 대한 멋진 플러그인 을 가지고 있습니다 .


이 플러그인을 사용하면 :default스키마 마이그레이션 의 값 이로만 작동 Model.new합니다.
jchook

Jeff가 자신의 직책에서 말한 것과는 달리 :default마이그레이션으로 '가치 만 작동' 할 수있는 가치를 얻을 수 있습니다 Model.new. Rails 4.1.16에서 작동하는지 확인했습니다.
Magne


8

나는 보석을 사용한다attribute-defaults

설명서에서 : 앱을 실행 sudo gem install attribute-defaults하고 추가 require 'attribute_defaults'하십시오.

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"

7

비슷한 질문이지만 모든 내용이 약간 다릅니다.- Rails activerecord의 모델에서 속성의 기본값을 어떻게 만들 수 있습니까?

가장 좋은 답변 : 당신이 원하는 것에 달려 있습니다!

모든 객체를으로 시작 하려면 다음을 사용하십시오.after_initialize :init

당신은 원하는 new.html형태로 페이지를 열 때 디폴트 값을 가지고? 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 

당신이 원하는 경우 모든 개체가하는 값은 사용자의 입력으로부터 계산 한 : 사용before_save :default_values 당신은 사용자가 입력하고자X다음과Y = X+'foo'? 사용하다:

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status ||= 'P'
  end
end

4

이것이 생성자를위한 것입니다! 모델의 initialize방법을 재정의하십시오 .

after_initialize방법을 사용하십시오 .


2
일반적으로 정확하지만 ActiveRecord 모델의 초기화를 항상 재정의해서는 안됩니다. 항상 호출되는 것은 아닙니다. after_initialize대신 이 방법을 사용해야합니다 .
Luke Redpath

default_scope를 사용하여 기본값을 설정하는 것은 엄청나게 잘못되었습니다. after_initialize가 정답입니다.
joaomilho

4

Sup 얘들 아, 나는 다음을 끝내었다.

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

매력처럼 작동합니다!


3

이것은 오랫동안 답변되었지만 기본값이 자주 필요하며 데이터베이스에 저장하지 않는 것이 좋습니다. 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

그런 다음 내 모델에서 다음과 같이 사용하십시오.

class Widget < ApplicationRecord
  include DefaultValues

  defaults :category, to: 'uncategorized'
  defaults :token, to: -> { SecureRandom.uuid }
end

3

또한 사람들이 마이그레이션에 넣는 것을 보았지만 모델 코드에 정의 된 것을 보았습니다.

ActiveRecord 모델에서 필드의 기본값을 설정하는 정식 방법이 있습니까?

Rails 5 이전의 정식 Rails 방식은 실제로 마이그레이션에서 설정 한 것입니다. db/schema.rb 설정하고 모든 모델에 대해 DB에서 어떤 기본값이 설정되어 있는지 확인하고자 할 때마다를 .

@Jeff Perrin의 답변 상태 (약간 오래된 것)와 달리 마이그레이션 방법은 사용할 때 기본값을 적용합니다. Model.new Rails의 일부 마법 때문에을 . Rails 4.1.16에서 작동하는지 확인했습니다.

가장 간단한 것이 종종 최고입니다. 코드베이스에 대한 지식 부채와 혼동의 가능성이 줄어 듭니다. 그리고 그것은 '그냥 작동합니다'.

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

또는 새 열을 만들지 않고 열을 변경하려면 다음 중 하나를 수행하십시오.

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

또는 아마도 더 나을 수도 있습니다.

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

열 변경 방법의 옵션에 대해서는 공식 RoR 안내서 를 확인하십시오 .

null: false것을 허용하지는이 혜택을 추가로, 그것도 널 (null) 이전에 있던 모든 기존 DB 레코드뿐만 아니라이 분야에 대한 기본 값으로 설정되도록 업데이트, DB에 값을 NULL합니다. 원하는 경우 마이그레이션에서이 매개 변수를 제외 할 수 있지만 매우 유용합니다!

@Lucas Caton이 말한 것처럼 Rails 5+의 정식 방법은 다음과 같습니다.

class Item < ActiveRecord::Base
  attribute :scheduler_type, :string, default: 'hotseat'
end

1

after_initialize 솔루션의 문제점은이 속성에 액세스하는지 여부에 관계없이 DB에서 조회하는 모든 단일 오브젝트에 after_initialize를 추가해야한다는 것입니다. 게으른로드 방식을 제안합니다.

속성 메소드 (getter)는 물론 메소드 자체이므로이를 대체하고 기본값을 제공 할 수 있습니다. 다음과 같은 것 :

Class Foo < ActiveRecord::Base
  # has a DB column/field atttribute called 'status'
  def status
    (val = read_attribute(:status)).nil? ? 'ACTIVE' : val
  end
end

다른 사람이 지적하지 않은 한 Foo.find_by_status ( 'ACTIVE')를 수행해야합니다. 이 경우 DB가 지원하는 경우 데이터베이스 제약 조건에서 기본값을 설정해야한다고 생각합니다.


이 솔루션과 제안 된 대안은 제 경우에는 작동하지 않습니다. 단 하나의 클래스에만 해당 속성이있는 STI 클래스 계층 구조와 DB 쿼리 조건에 사용되는 해당 열이 있습니다.
cmoran92

1

나는 문제로 실행 after_initialize주고 ActiveModel::MissingAttributeError복잡한 발견을하고 오류를 :

예 :

@bottles = Bottle.includes(:supplier, :substance).where(search).order("suppliers.name ASC").paginate(:page => page_no)

"검색" .where은 조건의 해시입니다

그래서 나는 이런 식으로 초기화를 재정 의하여 끝내 었습니다.

def initialize
  super
  default_values
end

private
 def default_values
     self.date_received ||= Date.current
 end

super호출은 반드시 개체에서 제대로 초기화 할 필요가있다 ActiveRecord::Base즉, 내 사용자 정의 코드를 수행하기 전에 : default_values


나는 그것을 좋아한다. def initialize(*); super; default_values; endRails 5.2.0에서 해야 했습니다. 또한 .attributes해시 에서도 기본값을 사용할 수 있습니다 .
spyle

1
class Item < ActiveRecord::Base
  def status
    self[:status] or ACTIVE
  end

  before_save{ self.status ||= ACTIVE }
end

2
음 ... 처음에는 독창적이지만 조금 생각하면 몇 가지 문제가 있습니다. 첫째, 모든 기본값은 단일 지점이 아니지만 클래스를 통해 흩어져 있습니다 (값을 검색하거나 변경한다고 상상해보십시오). 둘째, 최악의 경우 나중에 나중에 null 값 (또는 잘못된 값)을 넣을 수 없습니다.
paradoja

왜 널값을 기본값으로 설정해야합니까? 아무것도하지 않고 AR을 사용하여 즉시 사용할 수 있습니다. 부울 열을 사용할 때 false에 대해서는 맞습니다.이 방법은 최선의 방법이 아닙니다.
Mike Breen

클래스 파일 주위에 게터 / 세터를 흩 뜨리지 않기 때문에 문제가 없었던 다른 코딩 습관에 대해서는 말할 수 없습니다. 또한 최신 텍스트 편집기를 사용하면 메서드 (텍스트 메이트의 shift-cmd-t)로 쉽게 이동할 수 있습니다.
Mike Breen

@ paradoja-다시 가져 와서 null을 사용하여 어디서 고장 나는지 알 수 있습니다. 반드시 null을 기본값으로 사용할 필요는 없지만 실제로 어느 시점에서 값을 null로 변경하려는 경우. @paradoja를 잘 잡아 주셔서 감사합니다.
Mike Breen

동적으로 생성 된 속성과 잘 작동하므로이 방법을 사용합니다.
데일 캠벨


0

after_initialize 메소드는 더 이상 사용되지 않으며 대신 콜백을 사용하십시오.

after_initialize :defaults

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

그러나 마이그레이션에서 : default 를 사용하는 것이 여전히 가장 깨끗한 방법입니다.


4
Rails 3에서는 after_initializemethod 가 사용 되지 않습니다 . 실제로, 매크로 스타일의 콜백IS에 대한 예를 제공 하지 않습니다 . 세부 사항 : guides.rubyonrails.org/…
Zabba

0

유효성 검사 방법을 사용하면 기본값을 설정하는 데 많은 제어가 가능하다는 것을 알았습니다. 업데이트에 대한 기본값을 설정하거나 유효성 검사에 실패 할 수도 있습니다. 원하는 경우 삽입 대 업데이트에 대해 다른 기본값을 설정하기까지합니다. #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 방법을 정의에 관한 http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find


저장하기 전에 만 유효성 검사가 수행되지 않습니까? 저장하기 전에 기본값을 표시하려면 어떻게해야합니까?
nurettin

@nurettin 그것은 좋은 지적이며 왜 때때로 당신이 그것을 원할 지 알 수 있지만 OP는 이것을 요구 사항으로 언급하지 않았습니다. 저장되지 않은 경우에도 모든 인스턴스에서 기본값을 설정하는 오버 헤드를 원하는지 스스로 결정해야합니다. 대안은 new조치를 재사용하기 위해 더미 오브젝트를 유지하는 것입니다.
켈빈

0

열은 '상태'형식 열 될 일이, 그리고 모델은 사용을 고려, 상태 머신의 사용에 빌려 준다 경우 aasm 보석을 , 그 후에 당신은 간단하게 할 수있는,

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

여전히 저장되지 않은 레코드의 값을 초기화하지는 않지만 자신 init이나 다른 것으로 롤링하는 것보다 약간 더 깨끗 하며 모든 상태의 범위와 같은 asam의 다른 이점을 얻습니다.



0

"default_value_for"gem을 사용하는 것이 좋습니다. https://github.com/FooBarWidget/default_value_for

gem이 수행하는 initialize 메소드를 대체해야하는 까다로운 시나리오가 있습니다.

예 :

DB 기본값은 NULL이고 모델 / 루비 정의 기본값은 "일부 문자열"이지만 실제로 는 어떤 이유로 든 값을 nil로 설정 합니다.MyModel.new(my_attr: nil)

여기에서 대부분의 솔루션은 값을 nil로 설정하지 않고 대신 기본값으로 설정합니다.

좋아, ||=접근 하는 대신에 my_attr_changed?...로 전환하십시오 .

그러나 이제 DB 기본값이 "일부 문자열"이고 모델 / 루비 정의 기본값이 "일부 다른 문자열"이라고 가정하지만 특정 시나리오에서는 값을 "일부 문자열"(db 기본값)로 설정 하려고 합니다.MyModel.new(my_attr: 'some_string')

이 발생합니다 my_attr_changed?되고 거짓 값이 차례로 당신의 루비 정의 기본 코드를 발사하고 "다른 문자열"에 값을 설정 한 DB를 기본적으로 일치하기 때문에 - 다시를, 당신이 원하지 않는 것을.


이러한 이유로 나는 after_initialize 훅으로 올바르게 수행 할 수 있다고 생각하지 않습니다.

다시, "default_value_for"gem이 올바른 접근 방식을 취하고 있다고 생각합니다 : https://github.com/FooBarWidget/default_value_for


0

여기에 조금 놀랐다는 해결책이 아직 추가되지 않았습니다.

두 부분이 있습니다. 첫 번째 부분은 실제 마이그레이션에서 기본값을 설정하고 두 번째 부분은 존재 여부를 확인하는 모델에서 유효성 검사를 추가하는 것입니다.

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

여기에서 기본값이 이미 설정되어 있음을 알 수 있습니다. 이제 유효성 검사에서 문자열 값이 항상 있는지 확인하려고합니다.

 validates :new_team_signature, presence: true

이 작업은 기본값을 설정하는 것입니다. (저는 "팀에 오신 것을 환영합니다") 그리고 한 단계 더 나아가 해당 객체에 대한 값이 항상 존재하는지 확인합니다.

희망이 도움이됩니다!


0
# 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

-2

레일 3에서 default_scope를 사용하십시오.

API 문서

ActiveRecord는 데이터베이스 (스키마)에 정의 된 기본값과 응용 프로그램 (모델)에 수행 된 기본값 간의 차이를 모호하게합니다. 초기화 중에 데이터베이스 스키마를 구문 분석하고 여기에 지정된 기본값을 기록합니다. 나중에 객체를 만들 때 데이터베이스를 건드리지 않고 해당 스키마 지정 기본값을 할당합니다.

토론


meta_where를 사용하는 경우 버그로 인해 default_scope가 새 AR 객체에 기본값을 할당하는 데 작동하지 않을 수 있습니다.
Viktor Trón

이 meta_where 문제가 수정되었습니다 [ metautonomous.lighthouseapp.com/projects/53011/tickets/…
Viktor Trón

3
사용하지 마십시오 default_scope. 이렇게하면 모든 쿼리가 설정 한 필드에이 조건을 추가하게됩니다. 거의 원하는 것이 아닙니다.
brad

@ brad, 당신이 언급하는 재미, 나는 완전히 동의합니다, 그것은 악입니다 :). stackoverflow.com/questions/10680845/… 에서 내 의견을 참조하십시오 .
Viktor Trón 2016 년

-3

API 문서 http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.htmlbefore_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

그의 제안되지 않은 것에 놀랐다


before_validation은 객체를 유지할 준비가 될 때까지 기본값을 설정하지 않습니다. 지속하기 전에 프로세스가 기본값을 읽어야하는 경우 값이 준비되지 않습니다.
mmell

어쨌든 유효성 검사 중에 기본값을 설정하지 마십시오. 심지어 해킹도 아닙니다. 초기화 중
Sachin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.