Rails: STI、継承、リロード! 開発環境のバグ

作成日 2013年01月02日  ·  3コメント  ·  ソース: rails/rails

868号は今日も残っているので、再開します。

私はruby-1.9.3-p362とrails3.2.9を使用しました

唯一の解決策は、子クラスを要求するか、 config.cache_classes = trueを使用することです。

> Support.all
 => [] 
> Employee
 => Employee(id: integer, type: string) 
> Administrator
 => Administrator(id: integer, type: string) 
> Support.all
 => [#<Administrator id: 1, type: "Administrator">, #<Employee id: 2, type: "Employee">] 
activerecord

最も参考になるコメント

これは、クラスの遅延読み込みを伴う開発モードでSTIを使用する場合の既知の制限です。 Railsにこれらのサブクラスを認識させるには、 require_dependencyを使用する必要があります。例:

# app/models/support.rb
class Support < User
end

require_dependency 'administrator'
require_dependency 'employee'

これらのサブクラスがたくさんある場合は、 Dir[]app内の特別なフォルダーを使用して、それらすべてをロードできます。例:

# app/models/user.rb
class User < ActiveRecord::Base
end

Dir["#{Rails.root}/app/users/*.rb"].each do |file|
  require_dependency file
end

または、3番目の方法は、リストをModel.descendantsにハードコーディングすることです。例:

# app/models/user.rb
class User < ActiveRecord::Base
  def self.descendants
    [Support, Administrator, Employee]
  end
end

私は最後のものを個人的に使用していませんが、うまくいくはずです。

全てのコメント3件

Rails4で再現しました

Rails 4.0.0.beta
Ruby 1.9.3p194

1.9.3p194 :001 > Administrator.create

1.9.3p194 :003 > Employee.create

1.9.3p194 :008 > Support.all
  Support Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."type" IN ('Support', 'Administrator', 'Employee')
 => #<ActiveRecord::Relation [#<Administrator id: 1, type: "Administrator">, #<Employee id: 2, type: "Employee">]> 

1.9.3p194 :009 > reload!
Reloading...
 => true 

1.9.3p194 :010 > Support.all
  Support Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."type" IN ('Support')
 => #<ActiveRecord::Relation []> 

これは、クラスの遅延読み込みを伴う開発モードでSTIを使用する場合の既知の制限です。 Railsにこれらのサブクラスを認識させるには、 require_dependencyを使用する必要があります。例:

# app/models/support.rb
class Support < User
end

require_dependency 'administrator'
require_dependency 'employee'

これらのサブクラスがたくさんある場合は、 Dir[]app内の特別なフォルダーを使用して、それらすべてをロードできます。例:

# app/models/user.rb
class User < ActiveRecord::Base
end

Dir["#{Rails.root}/app/users/*.rb"].each do |file|
  require_dependency file
end

または、3番目の方法は、リストをModel.descendantsにハードコーディングすることです。例:

# app/models/user.rb
class User < ActiveRecord::Base
  def self.descendants
    [Support, Administrator, Employee]
  end
end

私は最後のものを個人的に使用していませんが、うまくいくはずです。

私はこの種の問題を抱えており、それを機能させることができません。 私のモデルはA、B(およびそれ以上)<C、D(およびそれ以上)<Bです。
コードを変更すると、「初期化されていない定数B」が返されます。 require_dependencyをいくつかの方法で試しましたが、1)どのクラスを必要とするか(B?)、および2)どこでそれを行うかは実際にはわかりません。
これらのモデルは、いくつかの方法で他のモデルに関連付けられています。これは、ロード順序にも影響を与える可能性があります(たとえば、AはXに属し、Xは多くのBおよびCに属します)。

このページは役に立ちましたか?
0 / 5 - 0 評価