相当复杂,所以我会尽量做到简单。
我有一个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
我希望实体被分配一个类型(字符串),以便进一步查找(在一个控制器中,我需要实体的文本表示和实体类本身之间的映射)。
显然,我需要加载所有子类实体,这就是为什么我在实体上添加了最后一行。Rb装载所有其他的。(也尝试使用初始化器,但它没有帮助,因为它不会在代码更改时重新加载)。
我的问题如下:
- 启动服务器。通过查看一些调试打印,我可以看到所有其他类都被加载了,当我查看@@str_to_ent映射时-它被初始化了。我调用控制器。一切都很好。我一直用各种参数调用它-一切都很好。
- 我更改任何文件(添加空格行) 从现在开始,我将得到一个错误消息,说没有实体与给定的类型(实体)相关联。
我确实理解,当代码更改时,rails(在开发模式下)重新评估类文件。我也可以在我的调试打印中看到这一点。它需要实体。Rb类,因此用{}覆盖@@str_to_ent,但是尽管它需要'ip_entity. net '。和'phone_entity. Rb '。rb',似乎它实际上并没有评估它们,因为实体。With_type不会再次被调用,并且@@str_to_ent散列仍然为空。这就是导致问题的原因。
我可以克服这个问题的唯一方法是重新启动服务器,但这使得整个调试过程非常烦人…
有谁能提供解决方案吗?当我需要以某种方式"配置"我的类时(非常类似于"attr_accessible"或"validates_presence_of"),但我需要这些方法的动作即使在rails重新加载类时也与我保持一致,最佳实践是什么?(我对重新评估类没有问题,我的问题是它重新评估基类并跳过子类)。
谢谢,
扎克
如果我正确理解你想要实现的是所谓的单表继承。在模型上实现继承是Rails的默认行为。
在此文档中搜索单表继承。
我认为使用require_dependency
应该允许你重新加载子类:
class Entity
...
end
require_dependency 'ip_entity'
require_dependency 'phone_entity'