2

そのため、いくつかのモデルをセットアップしていますが、それらは 2 つの抽象基本クラスに基づいています (または、以前はクラスでした)。Datamapper の STI の処理で多くの問題に遭遇した後、Lighthouse ページで未解決のバグのように見えたので、モデルを DRY に保つためにすべてのプロパティを定義するモジュールを作成することにしました。残念ながら、私はスコーピングの問題を抱えており、問題をさらに複雑にしているのは、2 レベルの継承を使用しなければならないことです。これが私のコードです:

module Part
  def self.included(receiver)
    receiver.class_eval do
      include DataMapper::Resource
      property :id,       Serial
      #other junk
    end
  end
end

module HardDrive
  def self.included(receiver)
    receiver.class_eval do
      include Part
      property :kind,          Enum[:magnetic, :flash]
      #buncha crap here
    end
  end
end

class Fujitsu
  include HardDrive
  property :rev, String
end

私が得るエラーは次のとおりです。

uninitialized constant HardDrive::Enum (NameError)
from /usr/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/active_support/dependencies.rb:80:in `const_missing'
from ./app/models/hard_drive.rb:6:in `included'
from ./app/models/hard_drive.rb:4:in `class_eval'
from ./app/models/hard_drive.rb:4:in `included'
from ./app/models/hard_drives/fujitsu.rb:2:in `include'
from ./app/models/hard_drives/fujitsu.rb:2

私はここで途方に暮れています。これを解決する方法を知っている人はいますか?

4

1 に答える 1

2

列挙型はDataMapperモジュールの下で定義されており、HardDriveスコープはそれを解決しないようです。(理由を知りたいですか?)

Enumの代わりにDataMapper::Enumを配置するだけで、機能するはずです。

より一般的な議論では、これらの抽象化が本当に必要であると確信していますか?コードに見られる欠点の1つは、ロジックがデータベースではなくrubyモジュールに格納されているため、データベースでパーツやハードドライブを照会できないことです。

更新(著者からのコメント後)

一般的な答えは次のとおりです。STIを忘れてください。ORMは便利ですが、その最良の部分はSQLバックエンドの抽象化です。それらは永続化されたオブジェクトモデルを持つことができるという印象を与えますが、抽象化はしばしばリークし、STIは良い例です。ここでは詳しく説明しませんが、オンラインでリソースを見つけることができます。最善の方法は、1対1、1対多、多多の関係など、SQLモデリングのベストプラクティスに十分に近づいていることです。

これが更新されたバージョンです。私はそれをテストしませんでした、そしてメソッド名はおそらく間違っています、しかしあなたは考えを得るでしょう:

class Part
  property :serial_number
  has_one Manufacturer
end

class HardDisk
  property :technology
  property :platters
  property :model
  #...
  is_one Part
end

class Manufacturer
  property :name #Fujitsu, ...
  property :website
  #...
  has_many HardDisk, [:trough=>Part]
end
于 2009-12-31T22:11:05.787 に答える