问题
In plain java I'd use:
public User(String name, String email) {
this.name = name;
this.email = f(email);
this.admin = false;
}
However, I couldn't find a simple standard way to do in rails (3.2.3), with ActiveRecords.
1. override initialize
def initialize(attributes = {}, options = {})
@name = attributes[:name]
@email = f(attributes[:email])
@admin = false
end
but it might be missed when creating a record from the DB
2. using the after_initialize
callback
by overriding it:
def after_initialize(attributes = {}, options = {})
...
end
or with the macro:
after_initialize : my_own_little_init
def my_own_little_init(attributes = {}, options = {})
...
end
but there may be some deprecation issues.
There are some other links in SO, but they may be out-of-date.
So, what's the correct/standard method to use?
回答1:
Your default values should be defined in your Schema when they will apply to ALL records. 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
Here, every new Post will have false for published. If you want default values at the object level, it's best to use Factory style implementations:
User.build_admin(params)
def self.build_admin(params)
user = User.new(params)
user.admin = true
user
end
回答2:
According to Rails Guides the best way to do this is with the after_initialize. Because with the initialize we have to declare the super, so it is best to use the callback.
回答3:
One solution that I like is via scopes:
class User ...
scope :admins, where(admin: true)
Then you can do both: create new User in the admin status(i.e. with admin
==true
) via User.admins.new(...)
and also fetch all your admins in the same way User.admins
.
You can make few scopes and use few of them as templates for creating/searching. Also you can use default_scope
with the same meaning, but without a name as it is applied by default.
回答4:
I was searching for something similar this morning. While setting a default value in the database will obviously work, it seems to break with Rails' convention of having data integrity (and therefore default values?) handled by the application.
I stumbled across this post. As you might not want to save the record to the database immediately, I think the best way is to overwrite the initialize method with a call to write_attribute()
.
def initialize
super
write_attribute(name, "John Doe")
write_attribute(email, f(email))
write_attribute(admin, false)
end
回答5:
This will work in 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
来源:https://stackoverflow.com/questions/10505166/how-to-initialize-an-activerecord-with-values-in-rails