How to initialize an ActiveRecord with values in Rails?

微笑、不失礼 提交于 2019-11-27 23:18:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!