Railsプロジェクトのインポート可能な懸念を書いているところです。この懸念は、csv ファイルを Importable を含む任意のモデルにインポートするための一般的な方法を提供します。
モデルごとに、インポート コードが既存のレコードを検索するために使用するフィールドを指定する方法が必要です。懸念事項に対してこのタイプの構成を追加する推奨される方法はありますか?
Railsプロジェクトのインポート可能な懸念を書いているところです。この懸念は、csv ファイルを Importable を含む任意のモデルにインポートするための一般的な方法を提供します。
モデルごとに、インポート コードが既存のレコードを検索するために使用するフィールドを指定する方法が必要です。懸念事項に対してこのタイプの構成を追加する推奨される方法はありますか?
もう少し「普通に見える」解決策です。懸念に引数を渡す必要を避けるために (偶然にも、正確にいくつかの csv インポートの問題のために) これを行います。エラーを発生させる抽象メソッドには長所と短所があると確信していますが、すべてのコードを 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
各モデルに懸念事項を含めるのではなく、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"
それが役立つことを願っています。これは私の個人的な見解にすぎませんが、他にも方法があります (それらについても知りたいです)。