bia*_*idp 104 ruby ruby-on-rails
我正在尝试找到在Rails中为对象设置默认值的最佳方法.
我能想到的最好的new方法是在控制器中设置方法的默认值.
如果可以接受或者有更好的方法,是否有人有任何意见?
SFE*_*ley 95
"正确"在Ruby中是一个危险的词.通常有多种方法可以做任何事情.如果您知道您将始终希望该表上该列的默认值,则在数据库迁移文件中设置它们是最简单的方法:
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
Run Code Online (Sandbox Code Playgroud)
因为ActiveRecord会自动发现您的表和列属性,所以这将导致在任何标准Rails应用程序中使用它的任何模型中设置相同的默认值.
但是,如果您只想在特定情况下设置默认值 - 比如,它是一个与其他一些共享表的继承模型 - 那么另一种优雅的方法是在创建模型对象时直接在Rails代码中执行:
class GenericPerson < Person
def initialize(attributes=nil)
attr_with_defaults = {:last_name => "Doe"}.merge(attributes)
super(attr_with_defaults)
end
end
Run Code Online (Sandbox Code Playgroud)
然后,当你这样做GenericPerson.new()时,Person.new()除非你用别的东西覆盖它,否则它总是会把"Doe"属性涓涓细流.
J-_*_*_-L 56
基于SFEley的答案,这里是针对较新的Rails版本的更新/修复版本:
class SetDefault < ActiveRecord::Migration
def change
change_column :table_name, :column_name, :type, default: "Your value"
end
end
Run Code Online (Sandbox Code Playgroud)
Ian*_*ton 20
首先,你不能超载,initialize(*args)因为在所有情况下都没有调用.
您最好的选择是将默认值放入迁移中:
add_column :accounts, :max_users, :integer, :default => 10
Run Code Online (Sandbox Code Playgroud)
第二个最好的方法是将默认值放入模型中,但这只适用于最初为零的属性.您可能会遇到与boolean列相关的问题:
def after_initialize
if new_record?
max_users ||= 10
end
end
Run Code Online (Sandbox Code Playgroud)
您需要new_record?这样,默认值不会覆盖从数据库加载的值.
您需要||=阻止Rails覆盖传递给initialize方法的参数.
Seb*_*yet 13
您也可以尝试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
Run Code Online (Sandbox Code Playgroud)
change_column_default Rails API文档
如果您指的是ActiveRecord对象,那么您有两种以上的方法:
例如
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
Run Code Online (Sandbox Code Playgroud)
更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
例如 before_validation_on_create
更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
在Ruby on Rails v3.2.8中,使用after_initializeActiveRecord回调,您可以在模型中调用一个方法,该方法将为新对象分配默认值.
对于由查找程序找到并实例化的每个对象,触发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
Run Code Online (Sandbox Code Playgroud)
Foo.bar = default_value对于此实例,除非实例包含attribute_whose_presence_has_been_validated先前的保存/更新.该default_value项目就会在结合使用视图渲染使用形式default_value的bar属性.
至多这是hacky ......
而不是检查属性值,使用new_record?带有rails 的内置方法.所以,上面的例子应该是这样的:
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
Run Code Online (Sandbox Code Playgroud)
这更清洁.啊,Rails的魔力 - 它比我更聪明.
小智 5
至少对于Rails 3.2.6中的布尔字段,这将适用于您的迁移.
def change
add_column :users, :eula_accepted, :boolean, default: false
end
Run Code Online (Sandbox Code Playgroud)
在这里放置一个1或者0一个默认值是不行的,因为它是一个布尔字段.它必须是一个true或一个false值.
如果您正在处理模型,则可以在 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
102531 次 |
| 最近记录: |