2012-09-16 62 views
0

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:密码,在轨控制台,我在执行时遇到一个错误:

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 

它不会工作,为什么??。

回答

8

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

attr_accessor,本地Ruby方法,该方法定义了一个吸气剂和用于类的实例的setter方法:

class User 
    attr_accessor :password 
end 

u = User.new 
u.password = "secret" 
u.password # => "secret" 

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,以防止你的模型的某些属性干预:在attr_accessible列举的属性可以通过模型的质量,分配属性(而其他属性将被列入黑名单,不能改变)以后改变通过“外部人”(例如,你不希望你的“Account.superadmin”属性可以通过简单的表单提交来改变,这将是一个不好的安全问题)。

请注意,您可以单独更改的属性,不管他们的“白名单/黑名单”状态:

a.created_at = Time.now 

a.created_at # => 2012-09-16 10:03:14 
+0

我认为这是值得一提的是,这是为了防止同样的[质量,分配] (http://blog.mhartl.com/2008/09/21/mass-assignment-in-rails-applications/)问题,它允许[GitHub hack](http://www.extremetech.com/computing/) 120981-github-hacked-millions-of-projects-risk-being-being-modified-or-deleted)今年早些时候。 –

+0

很好,但是你是通过大规模分配来表达的吗? –

+0

分配,其中一个传入一组完整的属性,而不是一次一个地传递。例如,通过在上面链接的示例中使用:'@ user.update_attributes(params [:user])''。 'attr_accessible'表示“这没问题”,而没有提到'attr_accessible'的任何东西都假定需要单独显式更新。 –