1

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

在第 6.3.1 节中,我们通过创建和运行迁移脚本在数据库中创建一个 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 在幕后做了一些魔术,有人介意解释一下它在做什么吗?

谢谢!

4

2 回答 2

1

你是对的 - 这里实际发生的幕后的轨道魔法。

只要您有ActiveRecord::BaseActiveRecord 的后代,就会查看该类的数据库表并自动为您创建访问器——它们不会出现在类定义中。如果您来自像 C# 这样的语言,您之前必须手动执行此类操作,这似乎很疯狂。

ActiveRecord 正在做什么(这是一个非常淡化的解释,它所做的实际事情要复杂得多)有点像在你的类中粘贴以下代码:

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

  def password_digest=(val)
    @password_digest = val
  end

end

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

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

这种模式在 Rails 中很常见,而且您会经常看到。如果你还在学习 Ruby 或 Rails 框架,并且不能 100% 确定某些东西的来源,不要害怕更仔细地观察——所谓的 Rails '魔法' 经常发生,需要一些时间才能避免惊讶。当我第一次从其他语言迁移到 Rails 时,我就有了这样的经历。

于 2013-05-21T23:16:42.017 回答
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.

恭喜你进入第六章!

于 2013-05-21T23:00:37.633 回答