1

まず、Rubyオブジェクトモデルについての私の理解は、C、PHP、およびJavaに由来するため、ひどく不完全であるとしましょう。

現在、私のアプリケーションには複数のモデルで共有されている機能が含まれているため、その機能をモジュールに移動して、物事をドライに保つようにしています。各モデルには、シリアル化する必要のある「データ」属性があります。ただし、serialize呼び出しをモジュールに移動すると、機能させることができません。基本的なモデルは次のとおりです。

class MyModel < ActiveRecord::Base
  include MyApp::Data
end

そしてここにモジュールがあります:

module MyApp
  module Data
    serialize :data, ActiveRecord::Coders::Hstore

    def get_data(key)
      data && data[key]
    end

    def set_data(key, value)
      self.data = (data || {}).merge(key => value)
    end
  end
end

を含むモデルをインスタンス化しようとするとMyApp:Data、次のエラーが発生します。

NoMethodError: undefined method `serialize' for MyApp::Data:Module

MyModelインスタンス化するときに、data単に含めるだけで属性がシリアル化されるようにするにはどうすればよいMyApp::Dataですか?

編集:

私もこれを試しました:

module MyApp
  module Data
    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
      serialize :data, ActiveRecord::Coders::Hstore
    end

    def get_data(key)
      data && data[key]
    end

    def set_data(key, value)
      self.data = (data || {}).merge(key => value)
    end
  end
end

残念ながら、まだ同じエラーが発生しています。

4

1 に答える 1

2

あなたが書いたようserializeに、モジュールがロードされたときに呼び出されます。serialize へのメソッド呼び出しにはレシーバーがないため、Data モジュールで行われます。一方、モジュールを含むクラスでそれを呼び出したいとします。

フックを使用してこれを行うことができますself.included-モジュールがインクルードされ、インクルードを行っているクラスが引数として渡されるたびに呼び出されます。たとえば、

module Data
  def self.included(base)
    base.serialize ...
  end
end

アクティブサポートを使用すると、次のこともできます

module Data
  extend ActiveSupport::Concern

  included do
    serialize :data, ...
  end
end

self.included をセットアップし、モジュールではなく self がインクルード クラスになるようにブロックを評価します (これは、呼び出したいメソッドが保護/プライベートである場合に便利です - DSL のものはそうではありませんでいっぱいのときに読み取り可能base.send :blah

于 2012-12-15T19:47:36.567 に答える