【问题标题】:Inheritance and Polymorphism conflicting in ruby on railsruby on rails中的继承和多态冲突
【发布时间】:2009-06-28 13:05:17
【问题描述】:

我对 Ruby on Rails 有疑问。 我有几个模型类继承自同一个类,以便具有一些通用行为。

父类称为CachedElement。 其中一个孩子被称为Outcome。

我想要一个名为 Flow 的其他模型属于 CachedElement 的任何子代。 因此 Flow 有一个称为 element 的多态属性,它属于_to

当我创建一个属于 Outcome 的新流时,element_type 设置为父类“CachedElement”,而不是“Outcome”。

这很令人困惑,因为我有几种类型的 CachedElement 存储在不同的表中,element_id 指的是几个不同的元素。

简而言之,我希望 element_type 字段引用子类名而不是父类名。

我该怎么做?

【问题讨论】:

    标签: ruby-on-rails ruby inheritance polymorphism


    【解决方案1】:

    element_type 字段设置为父类,因为 ActiveRecord 期望您在从其他模型派生时使用单表继承。该字段将引用基类,因为它引用了存储每个实例的表。

    如果CachedElement 的孩子存储在他们自己的表中,使用Ruby 模块代替继承可能会更有帮助。在类之间共享逻辑的标准方法是使用混合而不是继承。例如:

    module Cacheable
      # methods that should be available for all cached models
      # ...
    end
    
    class Outcome < ActiveRecord::Base
      include Cacheable
      # ... 
    end
    

    您现在可以像以前一样轻松使用多态关联,并且element_type 将被设置为正确的类。

    【讨论】:

    • 谢谢,我就是这么做的,但是从模块中继承实例和类方法有点棘手
    【解决方案2】:

    该文件应该放在你的 lib 文件夹中。但... 你也可以做继承的事情。

    您需要做的就是告诉您父类充当抽象类。

    # put this in your parent class then try to save a polymorphic item again.
    # and dont forget to reload, (I prefer restart) if your gonna try this in
    # your console.
    def self.abstract_class?
      true
    end
    

    差不多就是这样,这对我来说有点出人意料,实际上真的 很难在文档和其他任何地方找到。

    Kazuyoshi Tlacaelel。

    【讨论】:

    • 这在 Rails 5 时代也很有帮助:-)
    【解决方案3】:

    谢谢,这就是我所做的,但是能够从模块中继承实例和类方法有点棘手

    类方法可以通过:

    module Cachable
      def self.included(base)
        base.extend(ClassMethods)
      end
    
      module ClassMethods
        def a_class_method
          "I'm a class method!"
        end
      end
    
      def an_instance_method
        "I'm an instance method!"
      end
    end
    
    class Outcome < ActiveRecord::Base
      include Cacheable
    end
    

    【讨论】:

    • 感谢您的留言,我就是这样做的。在 Ruby on Rails 项目中,您会将这个文件放在哪里:在 app/model 文件夹中,还是在 lib 文件夹中?
    • 我不是 ruby​​ on rails 大师,但我会把它放在 lib 中或用它制作一个 gem :-)
    【解决方案4】:

    如果你想通过 mixin (Module) 添加类方法和实例方法 那么我建议你将它们抽象到不同的模块中。

    module FakeInheritance
    
        def self.included(klass)
          klass.extend ClassMethods
          klass.send(:include, InstanceMethods)
        end
    
        module ClassMethods
          def some_static_method
            # you dont need to add self's anywhere since they will be merged into the right scope
            # and that is very cool because your code is more clean!
          end
        end
    
        module InstanceMethods
           # methods in here will be accessable only when you create an instance
        end
    end
    
    # fake inheritance with static and instance methods
    class CachedElement
      include  FakeInheritance
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-15
      • 2012-11-14
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      相关资源
      最近更新 更多