ruby/rails: 扩展或包含其他模块
ruby/rails: extending or including other modules
我把我的模块分开了,这样它们更容易阅读和搜索
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
中的方法扩展到目标 class,而不是组合多个 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 子模块中。
我把我的模块分开了,这样它们更容易阅读和搜索
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
中的方法扩展到目标 class,而不是组合多个 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 子模块中。