红宝石/导轨:扩展或包括其他模块 [英] ruby/rails: extending or including other modules

查看:50
本文介绍了红宝石/导轨:扩展或包括其他模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将模块分开,这样它们就更易于阅读和搜索

I separated my modules so they are easier to read and search like

lib
  features
    - running.rb
    - walking.rb
  features.rb

他们有

# lib/features/running.rb
module Features::Running
  extend ActiveSupport::Concern

  module ClassMethods
    def can_run
      ...
    end
  end
end

另一个是:

# lib/features/walking.rb
module Features::Walking
  extend ActiveSupport::Concern

  module ClassMethods
    def can_walk
      ...
    end
  end
end

有一天我可能会很多.

我的问题是,当我想将它们添加到模型中时,我需要

My problem is when I want to add them in a model, I'd need to

# Sample model
class Man < ActiveRecord::Base
  # Include features modules
  include Features::Walking
  include Features::Running

  # Define what man can do
  can_walk
  can_run
end

我想知道是否有办法创建另一个模块并将其全部包含在内.像这样:

I was wondering if there is a way to create another module and include all of them. Something like:

# lib/features.rb
module Features
  extend ActiveSupport::Concern

  extend Features::Walking
  extend Features::Running
end

所以我只需要添加

# Sample model
class Man < ActiveRecord::Base
  # Include features modules
  include Features

  # Define what man can do
  can_walk
  can_run
end

或者我应该怎么做?

编辑-解决方案

我现在基于@Chris解决方案获得了修复程序.我得到了这样的东西:

I got the fix now based on @Chris solution. I got something like this:

module Features
  FEATURES = %w(running walking)

  # include Features::Running
  FEATURES.each do |feature|
    send :include, "Features::#{feature.camelize}".constantize
  end

  module ClassMethods
    # include Features::Running::ClassMethods
    FEATURES.each do |feature|
      send :include, "Features::#{feature.camelize}::ClassMethods".constantize
    end
  end

  def self.included(base)
    base.send :extend, ClassMethods
  end
end

和我的其他功能模块现在是:

and my other feature modules are now:

# lib/features/running.rb
module Features::Running
  module ClassMethods
    def can_run
      ...
    end
  end
end

# lib/features/walking.rb
module Features::Walking
  module ClassMethods
    def can_walk
      ...
    end
  end
end

编辑-更新的解决方案

module Features
  FEATURES = [Running, Walking]

  # include Features::Running
  FEATURES.each do |feature|
    send :include, feature
  end

  module ClassMethods
    # include Features::Running::ClassMethods
    FEATURES.each do |feature|
      send :include, feature::ClassMethods
    end
  end

  def self.included(base)
    base.send :extend, ClassMethods
  end
end

推荐答案

您可以;您可能遇到的问题是ActiveSupport::Concern自动将ClassMethods中的方法扩展到目标类,而不是将多个ClassMethods子模块组合为一个.不幸的是,由于Ruby的周期性包含阻止代码,这很难自动完成,但是实际上您可以在没有AS :: Concern的情况下手动完成所有操作.

You can; the issue you're likely running into is that ActiveSupport::Concern automagically extends the methods in ClassMethods onto the target class, rather than combining multiple ClassMethods sub-modules into one. This is unfortunately a little hard to do automatically because of Ruby's cyclical include prevention code, but you can actually do it all manually without AS::Concern.

module Foo
  def foo
  end

  module ClassMethods
    def cfoo
    end
  end
end

module Baz
  def baz
  end

  module ClassMethods
    def cbaz
    end
  end
end

module Bar
  include Baz
  def bar
  end

  module ClassMethods
    include Baz::ClassMethods
    def cbar
    end
  end
end

module Stuff
  include Foo
  include Bar

  module ClassMethods
    include Foo::ClassMethods
    include Bar::ClassMethods
  end
end

class Final
  include Stuff
  extend Stuff::ClassMethods
end

这有点冗长,但是您可以随意编写各个部分,尽管您必须注意始终包含父模块,然后将ClassMethods包含在相应的ClassMethods子模块中.

This is a little more verbose, but you can compose pieces as deep as you want, though you have to be careful to always include the parent module and then include ClassMethods onto the corresponding ClassMethods submodule.

这篇关于红宝石/导轨:扩展或包括其他模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆