【问题标题】:How to call a parent class and instead create one of it's children?如何调用父类并创建其中一个子类?
【发布时间】:2016-02-24 01:34:43
【问题描述】:

我有一个这样的模型目录结构:

/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.

有没有办法在顶层目录中调用alert.rb上的create,并且根据传递的参数,它会创建一个孩子而不是alert.rb。

I.E. Alert.create({type:"panic_alert"})

它会创建并返回其中一种 panic_alert 类型的警报?

【问题讨论】:

    标签: ruby-on-rails ruby oop object model


    【解决方案1】:

    通过对类定义进行少量更改,例如从 ActiveRecord::Base 继承 Alert 而不是 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】:

    您可以使用constantizesafe_constantize 方法来执行此操作。他们所做的是获取一个字符串并尝试返回该字符串所指的类。例如:

    "BaseAlert".safe_constantize
    => BaseAlert
    

    def method_name(alert_type)
      alert_type.safe_constantize.create()
    end
    

    两者之间的区别是constantize 会在字符串不匹配时抛出错误,而safe_constantize 只会返回nil。请记住,如果您传入一个带下划线的字符串(比如panic_alert),那么您将不得不camelize 它。

    【讨论】:

      【解决方案3】:

      似乎在我上辈子之前我为此创建了StiFactory。也就是说,这些天我发现 STI 没有多大用处(因此缺乏维护)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-28
        • 1970-01-01
        • 1970-01-01
        • 2020-06-11
        • 2016-08-23
        • 1970-01-01
        • 1970-01-01
        • 2013-12-06
        相关资源
        最近更新 更多