设计和User.create

时间:2014-03-13 12:55:11

标签: ruby-on-rails devise

通常在我们创建模型时,比如说User,它的属性与数据库字段匹配。 例如,如果我的相应数据库表users_development包含字段namescore,那么当我创建User类的实例时,我只需键入user = User.create(:name => "MyName", :score => 85)

现在,Devise创建了一个包含字段emailencrypted_password的迁移文件,但我看不到字段password(从安全的角度来看,这是非常合乎逻辑的)。

在查看论坛帖子时,我看到了许多例子,例如User.create(:email =>"me@domain.com", :password => "foo")。那么,password来自哪里?它不是表users_development的字段。现场背后发生了什么?我查看了http://rubydoc.info/github/plataformatec/devise/master/Devise上的文档,但找不到任何解释。

2 个答案:

答案 0 :(得分:3)

User.create(:email => "me@domain.com", :password => "foo")不会直接创建包含这些确切字段的数据库记录。相反,它在参数哈希中为每对使用public_send("#{k}=", v)。所以真的,它在内部做了类似的事情:

user = User.new
user.email = "me@domain.com"
user.password = "foo"
user.save

即使您没有password数据库字段,也会更新encrypted_password字段的设计DatabaseAuthenticatable module adds a password= method

def password=(new_password)
  @password = new_password
  self.encrypted_password = password_digest(@password) if @password.present?
end

答案 1 :(得分:2)

来自设计源代码的

This method可以解决问题:

# Generates password encryption based on the given value.
 def password=(new_password)
   @password = new_password
   self.encrypted_password = password_digest(@password) if @password.present?
 end

当调用create,update属性,build等时,rails将尝试为方法field=调用每个字段,因此当您将:password => 'foo'传递给create时,它会执行类似的操作:

user = User.new
user.password = 'foo'
user.save

此方法允许使用未散列的密码构建模型,但是将散列的密码存储在数据库中。