Rails教程:6.3.1加密密码

时间:2013-05-21 22:37:08

标签: ruby-on-rails ruby

我正在阅读教程(我必须说这是一个很好的资源),我不太了解以下内容:

  

在6.3.1节中,我们通过创建和运行迁移脚本在db中创建一个password_digest列:

rails generate migration add_password_digest_to_users password_digest:string
bundle exec rake db:migrate
bundle exec rake db:test:prepare
bundle exec rspec spec/

然后在rails控制台上,我能够实例化一个用户模型对象并在其上设置password_digest:

irb(main):007:0> @user = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil,     password_digest: nil>
irb(main):008:0> @user.password_digest = "zzzz" => "zzzz"
irb(main):009:0> @user.password_digest => "zzzz"   

但是我在User模型类定义中看不到password_digest属性:

class User < ActiveRecord::Base
  attr_accessible :email, :name

  before_save { |user| user.email = email.downcase}

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, presence: true, length: {maximum: 50}
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false}
end

我认为Rails在幕后做了一些魔术,有人会介意解释它在做什么吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

你是对的 - 这里的实际情况 在幕后魔力

每当你有ActiveRecord::Base的后代时,ActiveRecord会查看该类的数据库表并自动为你创建访问器 - 它们不会显示在类定义中。如果您来自C#之类的语言,那么这似乎是疯狂,之后您必须手动执行此类操作。

ActiveRecord正在做什么(这是一个非常淡化的解释,实际上它做得更复杂)是在你的类中坚持以下代码:

class User < ActiveRecord::Base
  def password_digest
    @password_digest
  end

  def password_digest=(val)
    @password_digest = val
  end

end

另外需要注意的是,它不仅仅为您创建属性getter和setter - 它根据列的类型混合了某种类型的转换。查看this question以获取更多信息和一些可能的问题。

这样做的最终结果实际上是一种奖励,也是我喜欢rails的原因之一:你在数据库中定义一次列,然后将它放到模型类中免费。

这种模式对于Rails来说很常见,你会经常看到它。如果您仍在学习Ruby或Rails框架,并且您不能100%确定某些内容来自何处,请不要害怕看得更近 - 所谓的Rails'魔术'经常发生并且需要一些时间才能成为惊讶。当我第一次从其他语言转移到Rails时,我有这种经历。

答案 1 :(得分:0)

以下是一些类可以拥有一个在类定义中看不到的成员变量的方法:

class ActiveRecord
  def password_digest=(val)
    @x = val
  end
  def password_digest
    @x
  end
end


class User < ActiveRecord
end

me = User.new
me.password_digest = "hello"
puts me.password_digest   #=> "hello"

在运行时动态创建:

class User
end

User.class_eval do 
  attr_accessor :password_digest
end

me = User.new
me.password_digest = "hello"
puts me.password_digest   #=> "hello"

我在rails教程中发现的问题是:

1) It is extremely boring.

2) Because all you do is copy code.

祝贺你进入第6章!