我正在使用Ruby on Rails 3.2.2和Squeel gem。我有以下声明,我正在尝试重构 Mixin模块中的my_squeel_query
方法(因为它被我的许多模型使用):
# Note: 'article_comment_associations' and 'model_as_like_article_comment_associations'
# refer to database table names.
class Article < ActiveRecord::Base
def my_squeel_query
commenters.
.where{
article_comment_associations.article_id.eq(my{self.id}) & ...
}
end
end
class ModelAsLikeArticle < ActiveRecord::Base
def my_squeel_query
commenters.
.where{
model_as_like_article_comment_associations.article_id.eq(my{self.id}) & ...
}
end
end
我的问题是我可以不通过在Mixin模块中生成动态名称来重构article_comment_associations
和model_as_like_article_comment_associations
语句。也就是说,如果那是String
,我可以使用"#{self.class.to_s.singularize}_comment_associations"
之类的内容动态生成相关名称,如下所示:
class Article < ActiveRecord::Base
include MyModule
end
class ModelAsLikeArticle < ActiveRecord::Base
include MyModule
end
module MyModule
def my_squeel_query
commenters.
.where{
# Note: This code doesn't work. It is just an sample.
"#{self.class.to_s.singularize}_comment_associations".article_id.eq(my{self.id}) & ...
}
end
end
但是,由于不是我的情况,我无法“建立”名称并使my_squeel_query
在模型之间“共享”。
如何动态生成与Squeel gem相关的关联名称?我应该考虑以另一种方式进行重构吗?你有什么建议?
答案 0 :(得分:1)
如果您动态生成方法,则可以执行此操作。为此目的提供了Module.included
方法:
module ModuleAsLikeArticle
def self.included(base)
base.send(:define_method, "#{base.to_s.singularize}_comment_associations") do
# ...
end
end
end
使用include
导入模块时会触发此操作,并允许您创建专门为此定制的方法。
作为注释,您可能希望使用base.name.underscore.singularize
来获得更易读的方法名称。按照惯例,方法名称中不应包含大写字母,尤其不应作为第一个字符。
传统的Rails类型应用程序使用不同的方法,而是定义一个可用于按需创建这些类的方法:
module ModuleAsLikeArticle
def has_comments
base.send(:define_method, "#{base.to_s.singularize}_comment_associations") do
# ...
end
end
end
这将使用如下:
class ModelAsLikeArticle < ActiveRecord::Base
extend MyModule
has_comments
end
由于在调用has_comments
之前不会创建该方法,因此您可以安全地扩展ActiveRecord::Base
,然后在需要该功能的所有类中插入适当的调用。
答案 1 :(得分:1)
由于DSL是instance_evaled,你实际上可以这样说:
def my_squeel_query
base = self
commenters.
.where{
# Note: This code does work. Because it's awesome.
__send__("#{base.class.to_s.singularize}_comment_associations").
article_id.eq(my{self.id})
}
end
答案 2 :(得分:0)
我想你可能会在Rails Reflection
课程中找到你需要的东西(http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html),如页面所示,它允许您可以询问有关其关联和聚合的ActiveRecord类。