ruby-on-rails - ruby /rails : extending or including other modules

标签 ruby-on-rails ruby module

我将模块分开,以便它们更易于阅读和搜索

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

有一天我可能会拥有很多这样的东西。

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

# 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

我想知道是否有办法创建另一个模块并包含所有模块。像这样的东西:

# 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 解决方案得到了修复。我得到了这样的东西:

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

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

# 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。

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 子模块中。

关于ruby-on-rails - ruby /rails : extending or including other modules,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28575328/

相关文章:

javascript - TypeScript - 将模块/命名空间附加到窗口

python - 属性错误 : module '' has no attribute '__path__'

ruby - MRI Ruby 和 jRuby 的性能差异

perl - 如何有条件地使用 Perl 中的模块?

ruby-on-rails - PostsController 中的 NoMethodError#create 按照入门指南创建

css - 按 id 突出显示 Rails 3 中的当前页面

ruby-on-rails - Ruby 开发环境(OS X 与 Ubuntu)

ruby 字符串拆分问题

每个请求都会获取 JavaScript 资源

ruby-on-rails - Rails 5.2升级导致ErrorController失败,并显示通用错误页面