如何使用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