Nic*_*k B 3 ruby module ruby-on-rails mixins
Ruby 1.9.2 p290和Rails 3.0.9
我有一个.rb文件结构如下:
module M1
# .... some method defs ...
# Code in the middle, outside of any def:
if Rails.version >= '3'
class Railtie < ::Rails::Railtie
ActiveSupport.on_load :action_controller do
ActionController::Base.send :include, ::M1::M2 # <- throws an error..
end
end
end
module M2
# ... method defs ...
end
end
Run Code Online (Sandbox Code Playgroud)
该行ActionController::Base.send :include, ::M1::M2抛出一个NameError - 它找不到M2.
但是,当我将M2移动到M1的顶部时,它会毫无问题地解析引用.这只是Ruby的工作原理 - 解释器不会在第一遍中获取范围内的所有有效名称吗?你能解释一下这种行为吗?
这种行为的原因是Ruby文件从上到下读取.类的主体是可执行代码.因此,名称错误的简单原因是Ruby解释器尚未到达代码的那一部分.
所以,这实际上是完全合法的Ruby代码:
class Foo
puts "hello from inside a class"
end
Run Code Online (Sandbox Code Playgroud)
类的定义只是另一种表达方式.并且,就像Ruby中的每个表达式一样,它具有返回值,因此以下工作原理:
two = class Foo
def bar
end
1 + 1
end
Run Code Online (Sandbox Code Playgroud)
当您使用替代语法创建类时,它变得更加明显:
Foo = Class.new do
puts "Hello"
end
Run Code Online (Sandbox Code Playgroud)
唯一的区别是,当您以这种方式编写时,不要输入命名空间.
您已在ActiveRecord中看到此行为:
class Post < ActiveRecord::Base
has_many :comments
end
Run Code Online (Sandbox Code Playgroud)
这里has_many只是一个存在的方法调用ActiveRecord::Base.它将在加载文件时直接执行.这就是为什么一些参数has_many和其他关系作为字符串传递的原因.
class Post < ActiveRecord::Base
belongs_to :author, :class_name => "User"
end
Run Code Online (Sandbox Code Playgroud)
如果你要提到类User本身,它会引发一个NameError,因为User加载时可能没有Post加载.(在Rails中实际情况并非如此,因为Rails拦截了NameErrors并试图找到所需的文件,但除了这里的重点之外).存储关系的"定义",并且只有在稍后访问关系时,才会将这些部分放在一起.
在这方面,模块完全相同.
| 归档时间: |
|
| 查看次数: |
1171 次 |
| 最近记录: |