在我的应用程序中,我不得不与某些第三方软件接口,希望有一天能够更换。因此,我没有保留所有代码来映射我的模型数据和模型本身中第三方软件所需的表单,我为每个模型创建了一个mapper
模块,隔离了代码在某个时候很容易删除的地方。
所以我有以下内容:
app/
models/
people.rb
mappers/
people_mapper.rb
理想情况下,我希望自动在模型类中包含匹配名称的模块,就像帮助程序自动包含在同名视图中一样。自动包含帮助程序的方式/位置,这也是我添加自己的代码的最佳位置吗?
答案 0 :(得分:0)
module Mapper::Core
def self.included( base )
base.extend( ClassMethods )
end
module ClassMethods
# model class method to include matching module
# this will throw an error if matching class constant name does not exist
def has_mapping
@mapper_class = Kernel.const_get( "Mapper::#{self}Mapper" )
include @mapper_class
end
# an accessor to the matching class mapper may come in handy
def mapper_class
@mapper_class
end
end
end
然后require
和include
初始化程序中ActiveRecord::Base
中的模块(确保您的Mapper
模块需要“mappers”文件夹中的所有文件,或者使用config.autoload_paths
)。
如果您根本不想使用has_mapping
类方法,可以尝试覆盖ActiveRecord::Base
的{{1}}回调,但它可能会变得危险:
self.inherited
我没有尝试任何此类操作,因此谨慎行事。
编辑:
我写这篇文章的时候累了。有一种更简单的方法可以自动包含匹配模块: def self.included( base )
base.extend( ClassMethods )
base.instance_eval <<-EOF
alias :old_inherited :inherited
def self.inherited( subclass )
subclass.has_mapping
old_inherited( subclass )
end
EOF
end
用以下内容初始化:
module Mapper::Core
def self.included( base )
begin
mapper_class = Kernel.const_get( "Mapper::#{base.name}Mapper" )
base.instance_eval( "include #{mapper_class}" )
rescue
Logger.info "No matching Mapper Class found for #{base.name}"
end
end
end
所有继承类现在都将ActiveRecord::base.instance_eval( 'include Mapper::Core' )
,这将触发包含匹配类。