Ruby on rails 如何使用Rails中的值初始化ActiveRecord?

Ruby on rails 如何使用Rails中的值初始化ActiveRecord?,ruby-on-rails,activerecord,ruby-on-rails-3.2,Ruby On Rails,Activerecord,Ruby On Rails 3.2,在纯java中,我将使用: public User(String name, String email) { this.name = name; this.email = f(email); this.admin = false; } 然而,我在rails(3.2.3)中找不到使用ActiveRecords的简单标准方法 1.覆盖初始化 但在创建一个 2.在初始化后使用回调 通过覆盖它: def after_initialize(attributes = {}, options

在纯java中,我将使用:

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

然而,我在rails(3.2.3)中找不到使用ActiveRecords的简单标准方法

1.覆盖初始化 但在创建一个

2.在初始化后使用
回调
通过覆盖它:

def after_initialize(attributes = {}, options = {})
  ...
end
或使用宏:

after_initialize : my_own_little_init
def my_own_little_init(attributes = {}, options = {})
  ...
end
但可能有

有一些链接,但它们可能已过时



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

我喜欢的一种解决方案是通过示波器:

class User ...
   scope :admins, where(admin: true)
然后,您可以通过
User.admins.new(…)
以管理员状态创建新用户(即使用
admin
=
true
),并以相同的方式获取所有管理员


您可以创建几个范围,并将其中的几个用作创建/搜索的模板。您还可以使用与默认值含义相同但没有名称的
default\u scope

当默认值应用于所有记录时,应在模式中定义它们。所以

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
在这里,每一个新的帖子都会有虚假的发布。如果希望在对象级别使用默认值,最好使用Factory样式的实现:

User.build_admin(params)

def self.build_admin(params)
  user = User.new(params)
  user.admin = true
  user
end

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

我偶然发现了这个。由于您可能不想立即将记录保存到数据库中,我认为最好的方法是通过调用
write\u attribute()
覆盖initialize方法


根据Rails指南,最好的方法是使用。因为使用initialize我们必须声明super,所以最好使用回调。

这将在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


您已经可以在不需要任何自定义代码的情况下执行此操作:
User.new(:name=>'Bon',:email=>'bob@example.com)
。你想用不同的方法吗?你说得对。我想我问的是默认值,而不是在创建时传递的init值,或者对给定的输入进行一些操作,在构造时使用
default\u scope
是否有任何问题?构造器中的其他参数操作如何?如果您正在处理注释模型,并且希望为FBI保存已删除的注释,那么这很有用:)只需将默认范围设置为
where(deleted:false)
,您将永远不会遇到已删除的答案,除非您通过
Comment直接覆盖您的范围。where(deleted:true)
或通过
取消范围
方法:
注释。取消范围
。还有其他方法,但我喜欢这一种:)我对范围有点熟悉,但用于查找,而不是创建。然而,我正在寻找一种方法来正确初始化我的对象,而不是将它们“划分”到作用域中……默认作用域对于指定必须与当前模型一起加载的相关记录也非常有用。如果您不熟悉,则称之为“急切加载”。如果您发现自己反复加载相关模型并循环使用它们,那么可以通过这种方式显著减少数据库命中率:
default\u scope include::tags
。但这是另一个故事10倍。。。我已经与Hibernate的注释进行了足够长的斗争,现在就开始寻找等效的方法:)谢谢。因此,基本上,如果我想在所有用户实例(创建时)中使用规范化电子邮件,我应该使用
def self.build\u normalized(params)
factory方法?这将找到正确的创建方法的工作传递给我的代码的客户机。而且它并没有覆盖所有的执行路径。另外,rails中是否有工厂实用程序?还是一个标准模式?还有。。。如果我们在模式定义中放入默认值,在对象本身中放入任何其他init逻辑,这不是在代码中的不同位置(可能还有抽象级别)散布一个问题吗?@Asaf--我会使用db init值或工厂模式,而不是两者都使用。链接已关闭,创建后是否为新的初始化后的
?@JamesMcMahon否,初始化后仍为
。我更新了文档链接。近年来,我几乎完全避免了AR回调。对我来说,它们使测试更加困难,使我的模型更加复杂。我希望我的模型真的很愚蠢。出于某种原因,如果你尝试像Model.new(param1:arg1,param2:arg2)这样的操作,就会出现“ArgumentError:Error number of arguments(1代表0)”错误,如果你想动态写入属性(例如随机化键),Mauro的答案似乎更好我同意。您可能应该改为使用after\u initialize。仅供参考,实际上,在使用after\u initialize时,当我使用after\u initialize时,每次在具有随机化属性的模型上进行查找时,值都会更改,我不想更改,因为方法签名错误,所以无法工作,它只需要声明一个可选参数。我在下一个答案建议中添加了一个可选参数的示例。
def initialize
  super
  write_attribute(name, "John Doe")
  write_attribute(email,  f(email))
  write_attribute(admin, false)
end
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