对rails中的attr_accessor和attr_accessible感到困惑

这是一个简单的注册应用程序

schema.rb

create_table "users", :force => true do |t| t.string "email" t.string "password_hash" t.string "password_salt" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false 

User.rb

 attr_accessible :email, :password, :password_confirmation attr_accessor :password before_save :encrypt_password validates_confirmation_of :password validates_presence_of :password, :on => :create validates_presence_of :email validates_uniqueness_of :email . . . 

为什么在attr_accessible和attr_accessor中都使用密码?

当我删除attr_accessor:password时,在rails控制台中,我在执行时遇到错误:

 user = User.new user.password # => no method error 

但是当我执行这个:

 user = User.new user.email # => nil 

这意味着user.email在没有在attr_accessor中添加的情况下工作,为什么?!!

这也有效:

 user = User.new user.password_confirmation # => nil 

但当我删除:

 validates_confirmation_of :password 

它不会起作用,为什么?

attr_accessorattr_accessible ,尽管几乎完全相同的拼写,但绝对是不同的方法。

attr_accessor ,一个本机Ruby方法,它为类的实例定义一个getter和一个setter方法:

 class User attr_accessor :password end u = User.new u.password = "secret" u.password # => "secret" 

attr_accessible是Rails带来的一种方法,它的意思是将模型的已有属性“列入白名单”。 attr_accessible中枚举的属性可以稍后通过模型属性的质量分配进行更改(而其他属性将被列入黑名单且不可更改):

 class Account < ActiveRecord::Base # First, you define 2 attributes: "password" and "created_at" attr_accessor :password attr_accessor :created_at # Now you say that you want "password" attribute # to be changeable via mass-assignment, while making # "created_at" to be non-changeable via mass-assignment attr_accessible :password end a = Account.new # Perform mass-assignment (which is usually done when you update # your model using the attributes submitted via a web form) a.update_attributes(:password => "secret", :created_at => Time.now) a.password # => "secret" # "password" is changed a.created_at # => nil # "created_at" remains not changed 

您可以使用attr_accessible来防止“外人”干扰模型的某些属性(例如,您不希望您的“Account.superadmin”属性可以通过简单的表单提交进行更改,这将是一个糟糕的安全问题)。

请注意,您可以单独更改属性,无论其“白名单/黑名单”状态如何:

 a.created_at = Time.now a.created_at # => 2012-09-16 10:03:14