Ruby 在具有变量名的模块中定义类方法
我创建了一个包含在类中的模块。在这个模块中,我试图定义一个方法,该方法是不带过滤器的类名的downcased版本。因此ShowFilter将有一个名为show的方法,该方法返回类show。我得到了“命名错误: ShowFilter:Class“ 编辑:使用示例Ruby 在具有变量名的模块中定义类方法,ruby,module,mixins,class-method,Ruby,Module,Mixins,Class Method,我创建了一个包含在类中的模块。在这个模块中,我试图定义一个方法,该方法是不带过滤器的类名的downcased版本。因此ShowFilter将有一个名为show的方法,该方法返回类show。我得到了“命名错误: ShowFilter:Class“ 编辑:使用示例 class ShowController < ApplicationController def index ShowFilter.run params[:query] end end class ShowCont
class ShowController < ApplicationController
def index
ShowFilter.run params[:query]
end
end
class ShowController
当您定义过滤器::基本::ClassMethods
时,它会在该上下文中计算self,因此最终定义的方法是ClassMethods.ClassMethods
(因为gsub不会做任何事情)
与在Base中插入的包含钩子一样,您希望使用extended in-ClassMethods:
module Filters
module Base
module ClassMethods
@@filters = {}
def filter name, &block
@@filters[name] = block
end
def run query = {}
query.each do |name, value|
@@filters[name.to_sym].call(value) unless @@filters[name.to_sym].nil?
end
Object.const_get(self.to_s.gsub('Filter', ''))
end
def self.extended(base)
define_method(base.to_s.downcase.gsub('filter', '').to_sym) do
Object.const_get(self.to_s.gsub('Filter', ''))
end
end
end
def self.included base
base.extend ClassMethods
end
end
end
class ShowFilter
include Filters::Base
filter :title do |title|
self.show.where(:title => title)
end
end
是的,
show
方法在哪里?定义方法(self.name.downcase.gsub('filter'),''){self}我尝试了你的建议,新代码在原始问题中。我仍然得到错误。我试图为mongoid模型定义一个过滤器DSL。我希望能够在几个过滤器类中包含基本过滤器模块,并通过其名称“show”访问该过滤器的模型,而不是像“model”这样的泛型。好的,我更新了代码。我仍然不确定它应该归还什么。它是自过滤的吗?或者它可能是一个名为self.downcase.gsub('filter','')的模型
很抱歉,我可能在您工作时编辑了我的代码,请再次查看它返回的内容,应该会更清楚。谢谢你看这个!基本上,ShowFilter应该有一个类方法show来返回类show(不是一个实例,而是类本身)。一个类bug过滤器会有一个返回类bug的方法bug。好吧!好了。因此,给定WalrusFilter,您可以执行WalrusFilter.walrus
,这将返回类walrus
。还要确保删除Show类定义(我将从这里删除)。否则我会在这方面出错。
module Filters
module Base
module ClassMethods
@@filters = {}
def filter name, &block
@@filters[name] = block
end
def run query = {}
query.each do |name, value|
@@filters[name.to_sym].call(value) unless @@filters[name.to_sym].nil?
end
Object.const_get(self.to_s.gsub('Filter', ''))
end
def self.extended(base)
define_method(base.to_s.downcase.gsub('filter', '').to_sym) do
Object.const_get(self.to_s.gsub('Filter', ''))
end
end
end
def self.included base
base.extend ClassMethods
end
end
end
class ShowFilter
include Filters::Base
filter :title do |title|
self.show.where(:title => title)
end
end