问:如何在嵌套类中共享有关父类
的信息class Post
MODEL = self
extend PostMod
has_many :comments, :class_name => 'Post::Comment'
class Comment
include CommentMod
belongs_to :model, :class_name => "Post"
def method_in_comment
puts MODEL
end
end
class Another
end
end
module CommentMod
def method_in_mod1
puts self.class::MODEL
end
def method_in_mod2
puts MODEL
end
end
module PostMod
def method_in_mod1
puts self::Comment
end
end
b = Post::Comment.new
b.method_in_comment # Post
b.method_in_mod1 # uninitialized constant Post::Comment::MODEL (NameError)
b.method_in_mod2 # uninitialized constant CommentMod::MODEL (NameError)
这种设计的原因,在这个例子中(实际系统要复杂得多),就是通过“include module”为任何模型添加注释。多数民众赞成将添加控制器,视图和模型方法
所有型号的评论行为都类似。但是,如果需要调整某些内容,模型可以覆盖类Comment中的任何方法。
棘手的部分是,模块对顶级类(Post)和同级别的类(Comment和Another)一无所知,但是他们需要在它们上面调用一些类方法。< / p>
我现在正在使用class.name解析来获取顶级类的类名,但应该有另一种方法。
欢迎任何建议,包括更改设计。
更新
帖子和评论只是一个例子,我的项目中没有这个模型。
我正在从下划线非法(或CamelCase)迁移到嵌套类(从ArticleTranslation到Article :: Translation)。 这看起来对我来说更清楚了。 在previos版本中,我使用模型名称来调用类上的类方法(在ModelTranslation等上) 现在,在重构lib模块之后,我不再需要知道model_name。
但我陷入了陷阱: 在ruby中你可以重新打开类,比如
class Post < ActiveRecord::Base
end
class Post::Comment < ActiveRecord::Base
belongs_to :language
end
class Post::Comment::Another1 < ActiveRecord::Base
end
class Post::Comment::Another2 < ActiveRecord::Base
end
class Language < ActiveRecord::Base
has_many :post_comments, :class_name => "Post::Comment"
end
我有一个问题:如果在服务器启动后立即加载页面 - 一切正常 但是对该页面的下一次调用会引发错误:没有这样的关联;调用包含的模块方法 - 没有方法错误。 我认为,rails为Post :: Coment加载了错误的文件,最糟糕的是我无法调试此错误... 但这是另一个问题。
UPDATE2
第二个问题解决了。问题出在助手班。
答案 0 :(得分:1)
您能否澄清“仅通过”include module“”为任何模型添加评论。你的意思是你有一个ActiveRecord模型注释,你想多态地将它与许多其他模型相关联,例如。
Post
has_many :comments
Article
has_many :comments
...等?
答案 1 :(得分:1)
所以,基于你后来的评论,这里有点像你使用Module.extended之后的东西:
module PostMod
def self.extended(klass)
klass.send :include, InstanceMethods
end
module InstanceMethods
def method_in_mod1
puts "from PostMod#method_in_mod1: #{self.class.inspect}"
end
end
end
module CommentMod
def self.extended(klass)
klass.send :include, InstanceMethods
end
module InstanceMethods
def method_in_mod1
puts "from CommentMod#method_in_mod1: #{self.class.inspect}"
end
def method_in_mod2
puts "from CommentMod#method_in_mod2: #{self.class.ancestors.inspect}"
end
end
end
class Post
extend PostMod
class Comment
extend CommentMod
def method_in_comment
puts "from Post::Comment#method_in_comment: #{self.class.inspect}"
end
end
class Another
end
end
b = Post::Comment.new
b.method_in_comment # Post::Comment
b.method_in_mod1 # Post::Comment
b.method_in_mod2 # [Post::Comment, CommentMod::InstanceMethods, Object, Kernel]
虽然输出与您的示例不完全相同。可能很难以您尝试的方式共享类变量,因为您实际上并未使用任何继承,只是嵌套类。
您能否详细说明共享这些变量的意图,或许有更好的方法来实现目标?
答案 2 :(得分:1)
我通过重构代码解决了问题。因此不再需要共享class.name。如果我最需要这个是使用class.name.scan或匹配得到顶级类名,那么重构代码并删除class.name.scan =) 分享一个班级名称是一个坏主意。