1

クラスに含まれるモジュールを作成しました。モジュールで、Filter を使用しないクラス名の小文字バージョンであるメソッドを定義しようとしています。したがって、ShowFilter には、クラス Show を返す show というメソッドがあります。「NoMethodError: ShowFilter:Class の未定義のメソッド `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
        self
      end

      def self.extended(base)
        name = base.class.name.gsub(/filter/i, '')
        define_method(name.downcase.to_sym) { Kernel.const_get name }
      end


    end

    def self.included base
      base.extend ClassMethods
    end

  end

end


class ShowFilter
    include Filters::Base

    filter :name do |name|
        self.show.where(:name => name)
    end

end

EDIT:使用例

class ShowController < ApplicationController
  def index
    ShowFilter.run params[:query]
  end
end
4

1 に答える 1

3

を定義するFilters::Base::ClassMethodsと、そのコンテキストで self が評価されるため、最終的に定義するメソッドはClassMethods.classmethods(gsub は何もしないため) です。

Base で利用した同梱のフックと同様に、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
于 2012-07-25T00:17:13.237 に答える