对rails中的attr_accessor和attr_accessible感到困惑

时间:2012-09-16 05:52:02

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.1

这是一个简单的注册申请

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

它不起作用,为什么??

1 个答案:

答案 0 :(得分:8)

attr_accessor attr_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