我正在为我的rails项目编写一个可导入的问题.这个问题将为我提供一种将csv文件导入包含Importable的任何模型的通用方法.
我需要一种方法让每个模型指定导入代码应该使用哪个字段来查找现有记录.是否有任何建议的方法可以为关注点添加此类配置?
Tom*_*son 11
一个稍微"看起来像香草"的解决方案,我们这样做(巧合的是,对于正好一些csv导入问题),以避免需要将参数传递给Concern.我确信错误提升抽象方法有利有弊,但它会将所有代码保存在app文件夹和您期望找到它的模型中.
在"关注"模块中,只是基础知识:
module CsvImportable
extend ActiveSupport::Concern
# concern methods, perhaps one that calls
# some_method_that_differs_by_target_class() ...
def some_method_that_differs_by_target_class()
raise 'you must implement this in the target class'
end
end
Run Code Online (Sandbox Code Playgroud)
在有关注的模型中:
class Exemption < ActiveRecord::Base
include CsvImportable
# ...
private
def some_method_that_differs_by_target_class
# real implementation here
end
end
Run Code Online (Sandbox Code Playgroud)
我建议创建一个ActiveRecord子模块并ActiveRecord::Base使用它扩展,而不是在每个模型中包含关注点,然后在该子模块(例如include_importable)中添加一个方法来执行包含.然后,您可以将字段名称作为参数传递给该方法,并在该方法中定义实例变量和访问器(例如importable_field),以保存字段名称,以便在Importable类和实例方法中进行引用.
所以像这样:
module Importable
extend ActiveSupport::Concern
module ActiveRecord
def include_importable(field_name)
# create a reader on the class to access the field name
class << self; attr_reader :importable_field; end
@importable_field = field_name.to_s
include Importable
# do any other setup
end
end
module ClassMethods
# reference field name as self.importable_field
end
module InstanceMethods
# reference field name as self.class.importable_field
end
end
Run Code Online (Sandbox Code Playgroud)
然后,您需要ActiveRecord使用此模块进行扩展,例如将此行放在初始化器(config/initializers/active_record.rb)中:
ActiveRecord::Base.extend(Importable::ActiveRecord)
Run Code Online (Sandbox Code Playgroud)
(如果问题出在您的config.autoload_paths身上,那么您不需要在此处提出要求,请参阅下面的评论.)
然后在你的模型中,你会包括Importable这样的:
class MyModel
include_importable 'some_field'
end
Run Code Online (Sandbox Code Playgroud)
而imported_field读者将返回字段的名称:
MyModel.imported_field
#=> 'some_field'
Run Code Online (Sandbox Code Playgroud)
在您InstanceMethods的实例中,您可以通过将字段名称传递给实例方法来设置导入字段write_attribute的值,并使用read_attribute以下方法获取值:
m = MyModel.new
m.write_attribute(m.class.imported_field, "some value")
m.some_field
#=> "some value"
m.read_attribute(m.class.importable_field)
#=> "some value"
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.这只是我对此的个人看法,但还有其他方法可以做到(我也有兴趣了解它们).
| 归档时间: |
|
| 查看次数: |
3184 次 |
| 最近记录: |