Наследование и полиморфизм, конфликтующие в рубине на рельсах - PullRequest
0 голосов
/ 28 июня 2009

У меня проблема с Ruby on Rails. У меня есть несколько классов моделей, которые наследуются от одного и того же класса, чтобы иметь общее поведение.

Родительский класс называется CachedElement. Один из детей называется Outcome.

Я хочу, чтобы другая модель под названием Flow принадлежала любому дочернему элементу CachedElement. Следовательно, у потока есть полиморфные атрибуты, называемые элементом, к которому он принадлежит_

Когда я создаю новый поток, который принадлежит Outcome, element_type устанавливается на «CachedElement», который является родительским классом, а не на «Outcome».

Это сбивает с толку, потому что у меня есть несколько типов CachedElement, которые хранятся в разных таблицах, element_id ссылается на несколько разных элементов.

Короче говоря, я бы хотел, чтобы поле element_type ссылалось на имя дочернего класса, а не на имя родительского класса.

Как я могу это сделать?

Ответы [ 4 ]

5 голосов
/ 28 июня 2009

Поле 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 голосов
/ 14 июля 2009

файл должен идти в вашей папке 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.

1 голос
/ 14 июля 2009

, если вы хотите добавить методы класса и методы экземпляра через миксин (Модуль) тогда я рекомендую вам абстрагировать их в разных модулях.

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
1 голос
/ 29 июня 2009

Спасибо, я так и сделал, но было довольно сложно унаследовать методы экземпляра и класса от модуля

Методы класса могут быть сделаны:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...