Rails에서 기본값을 설정하는 방법은 무엇입니까?
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()
립니다.
SFEley의 답변에 따라 다음은 최신 Rails 버전에 대한 업데이트 / 수정 된 것입니다.
class SetDefault < ActiveRecord::Migration
def change
change_column :table_name, :column_name, :type, default: "Your value"
end
end
우선 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 메소드에 전달 된 매개 변수를 재정의하지 못하도록 해야 합니다.
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
change_column_default Rails API 문서
ActiveRecord 객체를 참조하는 경우 다음 두 가지 방법이 있습니다.
1. DB에서 : default 매개 변수 사용
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
2. 콜백 사용
EG before_validation_on_create
자세한 정보 : http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
In Ruby on Rails v3.2.8, using the after_initialize
ActiveRecord callback, you can call a method in your model that will assign the default values for a new object.
after_initialize callback is triggered for each object that is found and instantiated by a finder, with after_initialize being triggered after new objects are instantiated as well (see ActiveRecord Callbacks).
So, IMO it should look something like:
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
for this instance unless the instance contains an attribute_whose_presence_has_been_validated
previously on save/update. The default_value
will then be used in conjunction with your view to render the form using the default_value
for the bar
attribute.
At best this is hacky...
EDIT - use 'new_record?' to check if instantiating from a new call
Instead of checking an attribute value, use the new_record?
built-in method with rails. So, the above example should look like:
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
This is much cleaner. Ah, the magic of Rails - it's smarter than me.
For boolean fields in Rails 3.2.6 at least, this will work in your migration.
def change
add_column :users, :eula_accepted, :boolean, default: false
end
Putting a 1
or 0
for a default will not work here, since it is a boolean field. It must be a true
or false
value.
In case you're dealing with a Model, you can use the Attriutes API in Rails 5+ http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
just add a migration with a proper column name and then in the model set it with:
class StoreListing < ActiveRecord::Base
attribute :country, :string, default: 'PT'
end
If you are just setting defaults for certain attributes of a database backed model I'd consider using sql default column values - can you clarify what types of defaults you are using?
There are a number of approaches to handle it, this plugin looks like an interesting option.
The suggestion to override new/initialize is probably incomplete. Rails will (frequently) call allocate for ActiveRecord objects, and calls to allocate won't result in calls to initialize.
If you're talking about ActiveRecord objects, take a look at overriding after_initialize.
These blog posts (not mine) are useful:
Default values Default constructors not called
[Edit: SFEley points out that Rails actually does look at the default in the database when it instantiates a new object in memory - I hadn't realized that.]
I needed to set a default just as if it was specified as default column value in DB. So it behaves like this
a = Item.new
a.published_at # => my default value
a = Item.new(:published_at => nil)
a.published_at # => nil
Because after_initialize callback is called after setting attributes from arguments, there was no way to know if the attribute is nil because it was never set or because it was intentionally set as nil. So I had to poke inside a bit and came with this simple solution.
class Item < ActiveRecord::Base
def self.column_defaults
super.merge('published_at' => Time.now)
end
end
Works great for me. (Rails 3.2.x)
A potentially even better/cleaner potential way than the answers proposed is to overwrite the accessor, like this:
def status
self['name_of_var'] || 'desired_default_value'
end
See "Overwriting default accessors" in the ActiveRecord::Base documentation and more from StackOverflow on using self.
Generate a migration and use change_column_default
, is succinct and reversible:
class SetDefaultAgeInPeople < ActiveRecord::Migration[5.2]
def change
change_column_default :people, :age, { from: nil, to: 0 }
end
end
i answered a similar question here.. a clean way to do this is using Rails attr_accessor_with_default
class SOF
attr_accessor_with_default :is_awesome,true
end
sof = SOF.new
sof.is_awesome
=> true
UPDATE
attr_accessor_with_default has been deprecated in Rails 3.2.. you could do this instead with pure Ruby
class SOF
attr_writer :is_awesome
def is_awesome
@is_awesome ||= true
end
end
sof = SOF.new
sof.is_awesome
#=> true
If you're talking about ActiveRecord objects, I use the 'attribute-defaults' gem.
Documentation & download: https://github.com/bsm/attribute-defaults
You could use the rails_default_value gem. eg:
class Foo < ActiveRecord::Base
# ...
default :bar => 'some default value'
# ...
end
https://github.com/keithrowell/rails_default_value
You can override the constructor for the ActiveRecord model.
Like this:
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
참고URL : https://stackoverflow.com/questions/1186400/how-to-set-default-values-in-rails
'program tip' 카테고리의 다른 글
PostgreSQL 데이터베이스에 대한 활성 연결 목록을 선택하는 방법 (0) | 2020.08.13 |
---|---|
파이썬에서 "예기치 않은 들여 쓰기"로 무엇을해야합니까? (0) | 2020.08.13 |
C ++ 열거 형은 서명되었거나 서명되지 않았습니까? (0) | 2020.08.13 |
UNIX 시대를 Date 객체로 변환 (0) | 2020.08.13 |
이미 업로드 된 Lambda 함수 다운로드 (0) | 2020.08.13 |