我有一个这样的模型目录结构:
/alerts
base_alert.rb
panic_alert.rb
hardware_alert.rb
alert.rb
使用/alerts/x_alert.rb模型设置如下:
class base_alert < ActiveRecord::Base
...
end
class panic_alert < base_alert
...
end
class hardware_alert < base_alert
...
end
etc.
有没有办法在top目录中调用alert.rb上的create,并且根据传递的参数,它会创建一个子节点而不是alert.rb。
即。 Alert.create({类型:&#34; panic_alert&#34;})
它会创建并返回一种panic_alert类型的警报吗?
答案 0 :(得分:1)
您可以使用constantize或safe_constantize方法执行此操作。他们做的是取一个字符串并尝试返回字符串引用的类。例如:
"BaseAlert".safe_constantize
=> BaseAlert
或
def method_name(alert_type)
alert_type.safe_constantize.create()
end
如果字符串不匹配,则constantize
之间的差异会引发错误,而safe_constantize
只会返回nil
。请记住,如果您传入一个下划线字符串(例如panic_alert
),那么您必须camelize。
答案 1 :(得分:1)
通过对类定义进行少量更改,例如从Alert
而不是ActiveRecord::Base
继承BaseAlert
,您可以实现您想要实现的目标。
以下是更新的课程:
# app/models/alert.rb
class Alert < ActiveRecord::Base
end
# app/models/alerts/base_alert.rb
module Alerts
class BaseAlert < ::Alert
end
end
# app/models/alerts/panic_alert.rb
module Alerts
class PanicAlert < BaseAlert
end
end
# app/models/alerts/hardware_alert.rb
module Alerts
class HardwareAlert < BaseAlert
end
end
以下是从基类创建子类的几种方法:
@panic_alert = Alert.create!(
type: 'Alerts::PanicAlert', #this has to be string
#other attributes
)
@alert = Alert.new
@alert.type = 'Alerts::PanicAlert' #this has to be string
# assign other attributes, if necessary
@alert.save
@alert = Alert.new
@panic_alert = @alert.becomes(Alerts::PanicAlert) #this has to be class
# assign other attributes, if necessary
@panic_alert.save
答案 2 :(得分:0)
在一生之前,我为此创建了StiFactory。也就是说,这些天我对STI没有多大用处(因此缺乏维护)。