如何为rails问题添加特定于模型的配置选项?

时间:2013-01-13 03:36:13

标签: ruby-on-rails

我正在为我的rails项目编写一个可导入的问题。这个问题将为我提供一种通用方法,可以将csv文件导入任何包含Importable的模型。

我需要为每个模型指定一种方法来指定导入代码应该使用哪个字段来查找现有记录。是否有任何建议的方法可以为关注点添加此类配置?

2 个答案:

答案 0 :(得分: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

在有关注的模型中:

class Exemption < ActiveRecord::Base
  include CsvImportable

  # ...

private
  def some_method_that_differs_by_target_class
    # real implementation here
  end
end

答案 1 :(得分:9)

我建议创建一个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

然后您需要使用此模块扩展ActiveRecord,例如将此行放入初始值设定项(config/initializers/active_record.rb)中:

ActiveRecord::Base.extend(Importable::ActiveRecord)

(如果问题出在您的config.autoload_paths,那么您不需要在此处提出要求,请参阅以下评论。)

然后在您的模型中,您将包含Importable,如下所示:

class MyModel
  include_importable 'some_field'
end

imported_field读者将返回该字段的名称:

MyModel.imported_field
#=> 'some_field'

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"

希望有所帮助。这只是我对此的个人看法,但还有其他方法可以做到(我也有兴趣了解它们)。