在类主体中声明的 Ruby 方法调用

我刚刚开始学习 ruby on ails,我遇到的代码如下:

class Post < ActiveRecord::Base
validates_presence_of   :title
belongs_to :user
end

类主体中有两个方法调用。 我很难找到任何 Ruby 文档 描述从类的主体内(但在任何方法之外)调用方法的工作方式。 我所有的书都只描述如何定义类和实例方法以及如何 从其他方法中调用它们。

我的问题是: 如何以及何时调用这些方法? 它们是如何定义的? 它们是否在某个活动记录模块中定义?

9922 次浏览

您看到的是 ActiveRecord 对象的类级方法。要编写自己的方法来执行这样的操作,您需要将它们作为插件编写,然后通过重新打开类定义将它们包含到 ActiveRecord 中。Ruby on Rails 插件创建指南:

Http://guides.rubyonrails.org/plugins.html

介绍如何编写这样一个插件/类级别的方法。关于如何理解这些类型的方法的含义以及它们如何与实例交互,这是一个很好的文档。

Re: How and when are these methods called?

在加载类时调用它们。您可以在其中一个方法中放置一个断点,并查看它是否作为 Rails 项目启动的一部分被调用。

How are they defined?

它们是类方法,因为它是 ruby,所以可以用很多方法来定义它们。

Are they mixins defined in some active record module?

在这种情况下,validates_presence_ofvendor/rails/activerecord/lib/active_record/validations.rb中定义,而 belongs_toActiveRecord是一个大系统,包括许多混合器、模块等。

注意,要查看定义方法的位置,我对每个方法都使用 http://www.gotapi.com/rubyrails,请参见定义底部的“ Show Source”链接。

类定义的主体和其他类一样是代码的执行上下文。这里的代码是在类的上下文中执行的(意味着 self是 Class 对象,它是 Class 的一个实例)。可以有局部变量和实例变量(它们属于类对象本身而不是类的实例) ,并且可以调用类对象响应的任何方法。一旦类定义块完成,代码就会运行。

在本例中,ActiveRecord: : Base 定义了类方法 validates_presence_ofbelongs_to

Yehuda Katz 在他的博客上对此做了很好的解释。

这些是类方法或“单例”方法。您应该熟悉 attr _ accessor。我们可以在测试类中实现类似的东西。

class Klass
def self.add_getter_and_setter(symbol)
module_eval "def #{symbol}; @#{symbol}; end"
module_eval "def #{symbol}=(val); @#{symbol} = val; end"
end
end


class Person < Klass
add_getter_and_setter :name
add_getter_and_setter :phone
end


person = Person.new
person.name = 'John Smith'
person.phone = '555-2344'
person # returns <Person:0x28744 @name="John Smith", @phone="555-2344">

在上面的例子中,我们使用‘ def self. add _ getter _ and _ setter’创建了类方法,但这不是唯一的方法。

class Klass
class << self # opens the singleton class
def add_getter_and_setter(symbol)  # note we dont specify self as it is already within the context of the singleton class
..
end
end
end

使用扩展。模块 # 扩展是一种用类方法扩展类的方法,同样,模块 # 包含的方法也包含一个用实例方法扩展类的方法。

class Klass
extend(Module.new do
def add_getter_and_setter(symbol)
..
end
end)
end

如果 Klass 已经被定义,我们可以重新打开它来添加类方法

class Klass
end


def Klass.add_getter_and_setter(symbol)
..
end


# or


class << Klass
def add_getter_and_setter(symbol)
..
end
end

这些是我知道的一些方法,如果你看到不同的语法,就会意识到它们都在做同样的事情。

注意: 在 rails 中,我们都使用的一个公共类方法是“ find”,它直接从 Model 类运行。

person = Person.find(1) # finds a person with id:1