我有一个名为DeviceState
的模型,其中包含“主动”,“离线”,“在线”等状态。
我有另一个名为Device
的模型belongs_to
到DeviceState
。
要在设备模型上使用@device.active?
和@device.offline?
等方法,我已经定义了一个动态方法,如下所示:
DeviceState.all.each do |method|
define_method((method.name + "?").to_sym) do
self.device_state.name == method.name
end
end
我的问题是,当我尝试在Device
模型上创建测试时,不会创建动态方法,因为在测试环境启动时尚未在数据库上填充DeviceState
模型。所以当我用工厂女孩创建DeviceState
数据时,为时已晚。
我尝试过的一个解决方案是在DeviceState
中播种spec_helper
,但是当这适用于第一次测试时,由于数据库清理程序删除了数据,因此它不适用于所有其他测试。
克服这些动态定义方法的最佳方法是什么?
答案 0 :(得分:0)
正如大家在评论中指出的那样,你应该根据数据库表使状态列表静态而不是动态。
如果您决定将此列表设为静态,请执行以下操作以避免每次添加状态时都必须编写新方法。
应用\模型\ devise.rb 强>
class Devise < ActiveRecord::Base
...
extend EnumFieldUtil
enum_field :devise_state, %w[active offline online]
...
end
使用您可以在lib
文件夹中定义的实用程序方法,以便在必要时可以在其他模型中重复使用
<强> LIB \ enum_field_util.rb 强>
module EnumFieldUtil
def enum_field(field, allowed_values)
allowed_values.each do |value|
class_eval %Q{
define_method("is_#{value}?") { self.#{field} == '#{value}' }
}
end
class_eval %Q{
validates_inclusion_of :#{field}, :in => #{allowed_values}, :message => "{{value}} must be in #{allowed_values.join ','}"
}
end
end