2012-09-16 59 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'的任何東西都假定需要單獨顯式更新。 –