我刚开始在rails上学习ruby,我遇到过如下代码:
class Post < ActiveRecord::Base
validates_presence_of :title
belongs_to :user
end
类体内有两个方法调用。 我很难找到任何ruby文档 描述了如何在类的主体内(但在任何方法之外)进行方法调用。 我拥有的所有书籍,仅描述了如何定义类和实例方法以及如何定义 从其他方法中调用它们。
我的问题是: 这些方法如何以及何时被称为? 他们是如何定义的?它们是否在某些活动记录模块中定义了mixins?
答案 0 :(得分:33)
类定义的主体是代码的执行上下文,就像任何其他代码一样。代码在类的上下文中执行(意味着self
是类对象,它是Class的一个实例)。您可以拥有本地变量和实例变量(它们将属于类对象本身而不是类的实例),您可以调用类对象响应的任何方法。一旦类定义块完成,代码就会运行。
在这种情况下,ActiveRecord :: Base定义类方法validates_presence_of
和belongs_to
。
答案 1 :(得分:17)
Yehuda Katz在他的博客上对此有一个很好的解释。见第4点:Class Bodies Aren't Special。
答案 2 :(得分:12)
Re:这些方法如何以及何时被调用?
[在课程加载时调用它们。您可以在其中一个方法中放置一个断点,并看到它是作为rails项目启动的一部分调用的。]
他们是如何定义的?
[他们是班级方法。由于这是红宝石,因此可以通过多种方式进行定义。]
它们是否在某些活动记录模块中定义了mixins?
[在这种情况下,
validates_presence_of定义于 供应商/轨道/了activerecord / LIB / active_record / validations.rb
belongs_to定义于 供应商/轨道/了activerecord / LIB / active_record / associations.rb
ActiveRecord是一个很大的系统,包括许多mixins,模块等。
注意,要查看定义方法的位置,我对每个方法使用http://www.gotapi.com/rubyrails,请参阅定义底部的“显示源”链接。
答案 3 :(得分:11)
这些是类方法或“单例”方法。您应该熟悉的是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
使用扩展。 Module#extend是一个使用类方法扩展类的方法,同样方法Module #include包含一个带有实例方法的类。
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
答案 4 :(得分:3)
您看到的是ActiveRecord对象的类级方法。要编写自己的方法,将其作为插件编写,然后通过重新打开类定义将它们包含到ActiveRecord中。 Ruby on Rails指南创建插件:
http://guides.rubyonrails.org/plugins.html
介绍如何编写这样的插件/类级方法。它是一个很好的文档,介绍如何围绕这些方法的含义以及它们与实例的交互方式。