如何使用Rails中的值初始化ActiveRecord?
在普通的java中我会使用:
public User(String name, String email) { this.name = name; this.email = f(email); this.admin = false; }
但是,我在使用ActiveRecords的rails(3.2.3)中找不到一种简单的标准方法。
1.覆盖初始化
def initialize(attributes = {}, options = {}) @name = attributes[:name] @email = f(attributes[:email]) @admin = false end
但是从DB创建记录时可能会错过
2.使用after_initialize
回调
通过覆盖它:
def after_initialize(attributes = {}, options = {}) ... end
或者用宏:
after_initialize : my_own_little_init def my_own_little_init(attributes = {}, options = {}) ... end
但可能存在一些弃用问题 。
SO中还有其他一些链接,但它们可能已过时。
那么, 使用的正确/标准方法是什么?
当应用于所有记录时,应在架构中定义默认值。 所以
def change creates_table :posts do |t| t.boolean :published, default: false t.string :title t.text :content t.references :author t.timestamps end end
在这里,每个新post都会有错误发布。 如果要在对象级别使用默认值,最好使用Factory样式实现:
User.build_admin(params) def self.build_admin(params) user = User.new(params) user.admin = true user end
根据Rails指南,最好的方法是使用after_initialize 。 因为初始化我们必须声明超级,所以最好使用回调。
我喜欢的一个解决方案是通过范围:
class User ... scope :admins, where(admin: true)
然后你可以做到这User.admins.new(...)
通过User.admins.new(...)
在管理状态(即使用admin
== true
)创建新用户,并以与User.admins
相同的方式获取所有管理员。
您可以制作一些范围,并使用其中的少数范围作为创建/搜索的模板。 您也可以使用具有相同含义的default_scope
,但默认情况下不使用名称。
今天早上我正在寻找类似的东西。 虽然在数据库中设置默认值显然会起作用,但它似乎打破了Rails的约定,即应用程序处理数据完整性(因此默认值?)。
我偶然发现了这篇文章 。 由于您可能不想立即将记录保存到数据库,我认为最好的方法是通过调用write_attribute()
来覆盖initialize方法。
def initialize super write_attribute(name, "John Doe") write_attribute(email, f(email)) write_attribute(admin, false) end
这将在轨道4中工作。
def initialize(params) super params[:name] = params[:name] + "xyz" write_attribute(:name, params[:name]) write_attribute(:some_other_field, "stuff") write_attribute(:email, params[:email]) write_attribute(:admin, false) end