0

かなり複雑なので、できるだけシンプルにしようと思います。

Railsアプリケーションがあり、開発モードで作業していて、サーバーの実行中にコードを変更すると問題が発生します。
私は次のモデルを持っています(もっと必要だと思うなら、関連するコードだけを使って-教えてください、そして私が追加します):

---- file : app/models/entity.rb ----
class Entity < ActiveRecord::Base

  @@str_to_ent = {}

  def self.with_type(given_type)
    given_type = given_type.to_sym
    if @@str_to_ent[given_type] and self!=@@str_to_ent[given_type]
      raise "Type #{given_type} was already associated by #{@@str_to_ent[given_type}"
    end
    @@str_to_ent[given_type] = self
  end

  def self.by_type(type)
    @@str_to_ent[type.to_sym]
  end

  # rest of code
end
Dir["#{File.dirname(__FILE__)}/*.rb"].each {|file| puts "requiring #{file}"; require file }


---- file : app/models/ip_entity.rb ----
class IpEntity < Entity
  with_type :ip

  # rest of code
end

---- file : app/models/phone_entity.rb ----
class PhoneEntity < Entity
  with_type :phone

  # rest of code
end

さらにルックアップするために、エンティティにタイプ(文字列)を割り当てたい(コントローラーの1つで、エンティティのテキスト表現とエンティティクラス自体の間のマップが必要です)。
明らかに、すべてのサブクラスエンティティをロードする必要があるため、他のすべてをロードするentity.rbの最後の行を追加しました。(初期化子も使用してみましたが、コードが変更されたときに再ロードされないため、役に立ちませんでした)。

私の問題は次のようになります:

  1. サーバーを起動します。いくつかのデバッグ出力を見ると、他のすべてのクラスがロードされていることがわかります。@@ str_to_entマップを見ると、初期化されています。
  2. 私はコントローラーを呼び出します。全て大丈夫。私はそれをさまざまな議論で呼び続けています-すべてが大丈夫です。
  3. いずれかのファイルを変更します(スペース行を追加します)
  4. これ以降、指定されたタイプに関連付けられているエンティティがないことを示すエラーメッセージが表示されます(Entity.by_typeは、以前に初期化されたタイプでnilを返しました)。

コードが変更されると、rails(開発モード)がクラスファイルを再評価することを理解しています。私のデバッグプリントでもそれを見ることができました。これはentity.rbクラスを必要とするため、@@ str_to_entを{}でオーバーライドしますが、「ip_entity.rb」と「phone_entity.rb」が必要ですが、Entity.with_typeがないため、実際には評価されないようです。再度呼び出されることはなく、@@str_to_entハッシュはまだ空です。それが問題の原因です。

私がこれを克服できる唯一の方法は、サーバーを再起動することですが、それはデバッグプロセス全体を非常に面倒にします...

誰かが解決策を手伝ってもらえますか?なんらかの方法でクラスを「構成」する必要がある場合のベストプラクティス(「attr_accessible」または「validates_presence_of」によく似ています)が、レールがクラスをリロードする場合でも、これらのメソッドのアクションが必要です。(クラスの再評価に問題はありません。私の問題は、ベースを再評価し、サブクラスをスキップすることです)。

ありがとう、
ザック

4

1 に答える 1

1

あなたが達成しようとしていることを正しく理解していれば、単一テーブルの継承と呼ばれます。モデルに継承を実装するときの Rails のデフォルトの動作です。

このドキュメントで単一テーブルの継承を検索してください。

アップデート

require_dependencyを使用すると、サブクラスもリロードできるはずだと思います:

class Entity
  ...
end
require_dependency 'ip_entity'
require_dependency 'phone_entity'
于 2012-12-23T15:45:16.840 に答える