27

在普通的java中,我会使用:

public User(String name, String email) {
  this.name = name;
  this.email = f(email);
  this.admin = false;
}

但是,我在 Rails (3.2.3) 中找不到使用 ActiveRecords 的简单标准方法。

1.覆盖初始化

def initialize(attributes = {}, options = {})
  @name  = attributes[:name]
  @email = f(attributes[:email])
  @admin = false
end

但是从数据库创建记录时可能会丢失

2.使用after_initialize回调

通过覆盖它:

def after_initialize(attributes = {}, options = {})
  ...
end

或使用宏:

after_initialize : my_own_little_init
def my_own_little_init(attributes = {}, options = {})
  ...
end

但可能存在一些弃用问题

SO 中还有一些其他链接,但它们可能已过时。


那么,使用的正确/标准方法是什么?

4

5 回答 5

20

当您的默认值适用于所有记录时,应在您的架构中定义它们。所以

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 都会有 false 表示已发布。如果你想要对象级别的默认值,最好使用工厂风格的实现:

User.build_admin(params)

def self.build_admin(params)
  user = User.new(params)
  user.admin = true
  user
end
于 2012-05-08T20:11:35.473 回答
16

根据 Rails Guides,最好的方法是使用after_initialize。因为用initialize我们要声明super,所以最好使用callback。

于 2013-04-07T13:50:15.770 回答
5

我喜欢的一种解决方案是通过范围:

class User ...
   scope :admins, where(admin: true)

然后你可以同时做:在管理员状态下创建新用户(即使用admin== true),User.admins.new(...)并以同样的方式获取所有管理员User.admins

您可以制作一些范围并将其中的一些用作创建/搜索的模板。您也可以使用default_scope相同的含义,但没有默认应用的名称。

于 2012-05-08T19:49:40.093 回答
4

今天早上我正在寻找类似的东西。虽然在数据库中设置默认值显然会起作用,但它似乎违反了 Rails 让应用程序处理数据完整性(因此默认值?)的约定。

我偶然发现了这篇文章。由于您可能不想立即将记录保存到数据库中,我认为最好的方法是通过调用来覆盖初始化方法write_attribute()

def initialize
  super
  write_attribute(name, "John Doe")
  write_attribute(email,  f(email))
  write_attribute(admin, false)
end
于 2012-10-13T08:13:58.213 回答
4

这将在 Rails 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
于 2016-08-08T00:41:49.120 回答