Ruby 在具有变量名的模块中定义类方法

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

我创建了一个包含在类中的模块。在这个模块中,我试图定义一个方法,该方法是不带过滤器的类名的downcased版本。因此ShowFilter将有一个名为show的方法,该方法返回类show。我得到了“命名错误: ShowFilter:Class“

编辑:使用示例

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