【问题标题】:Initialize a Ruby class depending on what modules are included根据包含的模块初始化 Ruby 类
【发布时间】:2012-01-30 14:25:50
【问题描述】:

我想知道根据包含的模块在 ruby​​ 中初始化类的最佳方法是什么。举个例子吧:

class BaseSearch
    def initialize query, options
        @page = options[:page]
        #...
    end
end


class EventSearch < BaseSearch
    include Search::Geolocalisable

    def initialize query, options
    end
end

class GroupSearch < BaseSearch
    include Search::Geolocalisable

    def initialize query, options
    end
end

module Search::Geolocalisable
    extend ActiveSupport::Concern

    included do
        attr_accessor :where, :user_location #...
    end
end

我不想要的是必须在每个包含 geolocalisable 模块的类上初始化 :where 和 :user_location 变量。

目前,我只是在我的模块中定义def geolocalisable?; true; end 之类的方法,然后,我在基类中初始化这些属性(由模块添加):

class BaseSearch
    def initialize query, options
        @page = options[:page]
        #...
        if geolocalisable?
            @where = query[:where]
        end
    end
end

class EventSearch < BaseSearch
    #...
    def initialize query, options
       #...
       super query, options
    end
end

有更好的解决方案吗?我希望如此!

【问题讨论】:

    标签: ruby-on-rails ruby module initialization


    【解决方案1】:

    查看此代码:

    module Search::Geolocalisable
      def self.included(base)
        base.class_eval do
          attr_accessor :where, :user_location #...
        end
      end
    end
    
    class EventSearch < BaseSearch
      include Search::Geolocalisable
    end
    

    【讨论】:

    • 问题不在于添加访问器。 ActiveSupport::Concern 和 included do; end 负责处理。这是关于找到一种在包含模块的每个类中初始化它们的好方法:)
    【解决方案2】:

    为什么不在模块中覆盖initialize?你可以这样做

    class BaseSearch
      def initialize query
        puts "base initialize"
      end
    end
    
    module Geo
      def initialize query
        super
        puts "module initialize"
      end
    end
    
    class Subclass < BaseSearch
      include Geo
      def initialize query
        super
        puts "subclass initialize"
      end
    end
    
    Subclass.new('foo') #=>
      base initialize
      module initialize
      subclass initialize
    

    显然,这确实需要包含您的模块的所有内容都使用类似的签名进行初始化,否则可能会发生奇怪的事情

    【讨论】:

    • 我会试试的,但是你知道在使用 ActiveSupport::Concern 时它的工作方式是否相同吗?在这种情况下,我认为包含的模块几乎不像您的示例中那样充当超类。
    • 好的,它的工作原理完全相同,您的解决方案正是我想要的,谢谢。我在搜索时随机学到的东西:调用super()super 不同。逻辑但仍然^^。
    猜你喜欢
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 2015-02-10
    • 2018-05-09
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    相关资源
    最近更新 更多