Rails에서 객체의 기본값을 설정하는 가장 좋은 방법을 찾으려고합니다.
내가 생각할 수있는 최선의 new
방법은 컨트롤러 의 메서드에서 기본값을 설정하는 것입니다 .
이것이 수용 가능하거나 더 나은 방법이 있다면 누구든지 의견을 가지고 있습니까?
Rails에서 객체의 기본값을 설정하는 가장 좋은 방법을 찾으려고합니다.
내가 생각할 수있는 최선의 new
방법은 컨트롤러 의 메서드에서 기본값을 설정하는 것입니다 .
이것이 수용 가능하거나 더 나은 방법이 있다면 누구든지 의견을 가지고 있습니까?
답변:
"정답"은 Ruby에서 위험한 단어입니다. 일반적으로 하나 이상의 방법이 있습니다. 해당 테이블의 해당 열에 대해 항상 기본값을 원한다는 것을 알고 있다면 DB 마이그레이션 파일에서 설정하는 것이 가장 쉬운 방법입니다.
class SetDefault < ActiveRecord::Migration
def self.up
change_column :people, :last_name, :type, :default => "Doe"
end
def self.down
# You can't currently remove default values in Rails
raise ActiveRecord::IrreversibleMigration, "Can't remove the default"
end
end
ActiveRecord는 테이블 및 열 속성을 자동 검색하기 때문에 표준 Rails 앱에서 사용하는 모든 모델에서 동일한 기본값이 설정됩니다.
그러나 특정 경우에만 기본값을 설정하려는 경우 (예 : 다른 테이블과 테이블을 공유하는 상속 된 모델) 다른 우아한 방법은 모델 객체가 생성 될 때 Rails 코드에서 직접 수행하는 것입니다.
class GenericPerson < Person
def initialize(attributes=nil)
attr_with_defaults = {:last_name => "Doe"}.merge(attributes)
super(attr_with_defaults)
end
end
그런 다음을 수행 할 때 다른 항목으로 재정의하지 않는 한 GenericPerson.new()
항상 "Doe"속성을 조금씩 떨어 뜨 Person.new()
립니다.
.new
클래스 메서드로 호출 된 새 모델 객체에서 작동합니다 . ActiveRecord 직접 호출 .allocate
에 대한 블로그 게시물의 토론은 데이터베이스에서 기존 데이터로로드 된 모델 객체에 대한 것이 었습니다. ( 그리고 이 일에 액티브에 대한 끔찍한 생각이 그런 식으로, IMO 그러나 그 점 옆의..)
change_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520
change_column :people, :last_name, :string, default: "Doe"
SFEley의 답변을 기반으로 다음은 최신 Rails 버전에 대한 업데이트 / 수정 된 것입니다.
class SetDefault < ActiveRecord::Migration
def change
change_column :table_name, :column_name, :type, default: "Your value"
end
end
change_column
매우 "구조"가 될 수 있으며, 역 동작을 추론 할 수 없습니다. 확실하지 않은 경우에, 다만 실행하여 테스트 db:migrate
및 db:rollback
직후. 동일한 결과로 받아 들인 대답이지만 적어도 가정합니다!
up
및 down
@GoBusto에서 설명한 것처럼
우선 initialize(*args)
모든 경우에 호출 되지 않으므로 오버로드 할 수 없습니다 .
가장 좋은 방법은 기본값을 마이그레이션에 적용하는 것입니다.
add_column :accounts, :max_users, :integer, :default => 10
두 번째로 좋은 방법은 기본값을 모델에 배치하는 것이지만 처음에는 nil 인 속성에서만 작동합니다. boolean
열에서 했던 것처럼 문제가있을 수 있습니다 .
def after_initialize
if new_record?
max_users ||= 10
end
end
new_record?
기본값이 데이터베이스에서로드 된 값을 재정의하지 않도록하기 위해 필요합니다 .
||=
Rails가 initialize 메소드에 전달 된 매개 변수를 재정의하지 못하도록 해야 합니다.
after_initiation :your_method_name
.... 2 사용self.max_users ||= 10
after_initialize do
대신def after_initialize
change_column_default
마이그레이션을 시도 할 수도 있습니다 (Rails 3.2.8에서 테스트 됨).
class SetDefault < ActiveRecord::Migration
def up
# Set default value
change_column_default :people, :last_name, "Smith"
end
def down
# Remove default
change_column_default :people, :last_name, nil
end
end
ActiveRecord 객체를 참조하는 경우 다음 두 가지 방법이 있습니다.
EG
class AddSsl < ActiveRecord::Migration
def self.up
add_column :accounts, :ssl_enabled, :boolean, :default => true
end
def self.down
remove_column :accounts, :ssl_enabled
end
end
자세한 정보 : http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
EG before_validation_on_create
자세한 정보 : http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
Ruby on Rails v3.2.8에서는 after_initialize
ActiveRecord 콜백을 사용하여 새 개체에 대한 기본값을 할당하는 모델의 메서드를 호출 할 수 있습니다.
after_initialize 콜백은 파인더에 의해 발견되고 인스턴스화 된 각 객체에 대해 트리거되며, after_initialize는 새 객체가 인스턴스화 된 후에도 트리거됩니다 ( ActiveRecord 콜백 참조 ).
따라서 IMO는 다음과 같이 보일 것입니다.
class Foo < ActiveRecord::Base
after_initialize :assign_defaults_on_new_Foo
...
attr_accessible :bar
...
private
def assign_defaults_on_new_Foo
# required to check an attribute for existence to weed out existing records
self.bar = default_value unless self.attribute_whose_presence_has_been_validated
end
end
Foo.bar = default_value
인스턴스에 attribute_whose_presence_has_been_validated
이전 저장 / 업데이트 가 포함되어 있지 않은 경우이 인스턴스의 경우 . 는 default_value
다음을 사용하여 폼 렌더링 할 뷰와 함께 사용됩니다 default_value
에 대한 bar
속성을.
기껏해야 해키입니다 ...
속성 값을 확인하는 대신 new_record?
레일과 함께 기본 제공 방법을 . 따라서 위의 예는 다음과 같습니다.
class Foo < ActiveRecord::Base
after_initialize :assign_defaults_on_new_Foo, if: 'new_record?'
...
attr_accessible :bar
...
private
def assign_defaults_on_new_Foo
self.bar = default_value
end
end
이것은 훨씬 더 깨끗합니다. 아, Rails의 마법-나보다 똑똑합니다.
after_initialize
여기서 콜백 을 추천하는 이유는 무엇 입니까? 콜백에 대한 Rails 문서에는 before_create
추가 조건 검사없이 기본값을 설정하는 예제 가 있습니다
Subscription
after_initialize
대신에, before_create
콜백, 우리가에 대한 기본 값을 설정하려는 것입니다 사용자 가 새로운 객체를 생성 할 때 (뷰에 사용). before_create
콜백이 호출 후 사용자가 새로운 객체를 제공하고있다, 자신의 입력을 제공하고, 컨트롤러에 창조를 위해 개체를 제출했다. 그런 다음 컨트롤러는 before_create
콜백 을 확인합니다 . 직관에 반하는 것처럼 보이지만 명명법 before_create
은 create
행동을 나타냅니다 . 새 개체를 인스턴스화하는 것은 개체가 아닙니다 create
.
모델을 다루는 경우 Rails 5 이상 http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute 에서 Attriutes API를 사용할 수 있습니다.
적절한 열 이름으로 마이그레이션을 추가 한 다음 모델에서 다음과 같이 설정하십시오.
class StoreListing < ActiveRecord::Base
attribute :country, :string, default: 'PT'
end
마이그레이션 생성 및 사용 change_column_default
은 간결하고 되돌릴 수 있습니다.
class SetDefaultAgeInPeople < ActiveRecord::Migration[5.2]
def change
change_column_default :people, :age, { from: nil, to: 0 }
end
end
데이터베이스 지원 모델의 특정 속성에 대한 기본값을 설정하는 경우 SQL 기본 열 값 사용을 고려할 것입니다. 사용중인 기본값 유형을 명확히 할 수 있습니까?
이를 처리하는 방법에는 여러 가지가 있으며이 플러그인 은 흥미로운 옵션처럼 보입니다.
새로 만들기 / 초기화를 재정의하라는 제안은 아마도 불완전 할 것입니다. Rails는 ActiveRecord 객체에 대해 allocate를 (자주) 호출하며, allocate 호출은 초기화 호출로 이어지지 않습니다.
ActiveRecord 객체에 대해 이야기하는 경우 after_initialize 재정의를 살펴보십시오.
다음 블로그 게시물 (내가 아님)은 유용합니다.
[편집 : SFEley는 Rails가 메모리에서 새 객체를 인스턴스화 할 때 실제로 데이터베이스의 기본값을 확인한다고 지적합니다. 저는 그것을 깨닫지 못했습니다.]
DB에서 기본 열 값으로 지정된 것처럼 기본값을 설정해야했습니다. 그래서 이렇게 작동합니다
a = Item.new
a.published_at # => my default value
a = Item.new(:published_at => nil)
a.published_at # => nil
after_initialize 콜백은 인자에서 속성을 설정 한 후 호출되기 때문에 속성이 설정되지 않았거나 의도적으로 nil로 설정 되었기 때문에 속성이 nil인지 알 방법이 없었습니다. 그래서 나는 약간의 내부를 들여다보고이 간단한 해결책을 가지고 왔습니다.
class Item < ActiveRecord::Base
def self.column_defaults
super.merge('published_at' => Time.now)
end
end
나를 위해 잘 작동합니다. (레일 3.2.x)
제안 된 답변보다 잠재적으로 더 좋고 / 깨끗한 잠재적 인 방법은 다음과 같이 접근자를 덮어 쓰는 것입니다.
def status
self['name_of_var'] || 'desired_default_value'
end
에서 "덮어 쓰기 기본 접근"을 참조하십시오 액티브 :: 자료 문서 및 더 자기를 사용하는 방법에 대한 유래 stackoverflow.com을 .
나는 여기에 비슷한 질문에 대답 했다 .. 이것을 수행하는 깨끗한 방법은 Rails attr_accessor_with_default를 사용하는 것입니다.
class SOF
attr_accessor_with_default :is_awesome,true
end
sof = SOF.new
sof.is_awesome
=> true
최신 정보
attr_accessor_with_default 는 Rails 3.2에서 더 이상 사용되지 않습니다. 대신 순수 Ruby로이 작업을 수행 할 수 있습니다.
class SOF
attr_writer :is_awesome
def is_awesome
@is_awesome ||= true
end
end
sof = SOF.new
sof.is_awesome
#=> true
attr_accessor_with_default
rails> 3.1.0
ActiveRecord 객체에 대해 이야기하는 경우 'attribute-defaults'gem을 사용합니다.
문서 및 다운로드 : https://github.com/bsm/attribute-defaults
rails_default_value gem을 사용할 수 있습니다. 예 :
class Foo < ActiveRecord::Base
# ...
default :bar => 'some default value'
# ...
end
ActiveRecord 모델의 생성자를 재정의 할 수 있습니다.
이렇게 :
def initialize(*args)
super(*args)
self.attribute_that_needs_default_value ||= default_value
self.attribute_that_needs_another_default_value ||= another_default_value
#ad nauseum
end