Node Inheritance Hierarchies

(Danny) #1

I have a blog which links to blog entries. There are different types of blog entries (video, article, image), but they all have common information such as an introduction and thumbnail.
How do I set up a class structure that supports this type of inheritance in push_type?
I want to reduce duplication

(Aaron Russell) #2

You have a few options - no right or wrong way.

1. A single Article class with a kind attribute

Something like this:

class Article < PushType::Node
  KINDS = %w( Article Image Video )
  field :kind, :select, choices: KINDS, validation: { required: true }
  field :introduction, :wysiwyg
  field :thumbnail_id, :asset
  field :media_id, :asset

So you just have one Article model, but in your template/view you can determine the “kind” of article and change the template accordingly.

2. Multiple nodes

To be honest, node classes tend to be quite small so I don’t think there’s any major DRY sin by just creating three different node classes. So from your Blog node:

class Blog < PushType::Node
  has_child_nodes :article, :image, :video, order: :blog

If the duplication really bothers you or you have quite a lot of other code that you want to be shared across the three child classes then you could always put them in a Concern and include that in each class.

3. Try actual inheritance

I’ve never tried this so I don’t even know if this would work… (but I’d be interested to find out). Define a base class with the shared code and 3 separate classes that inherit from the base. Eg:

class Blog < PushType::Node
  has_child_nodes :article, :image, :video, order: :blog

class BlogEntry < PushType::Node
  # ... shared code

class Article < BlogEntry
  # ... article code

class Image < BlogEntry
  # ... image code

class Video < BlogEntry
  # ... video code

(Danny) #3

The duplication is minimal at the moment but it is duplication nonetheless. I didn’t like the idea of copy pasting those fields into all blog entry type classes.

I did try that and it doesn’t work. PushType displays the, say Video, form but ignores any inherited fields such as introduction and thumbnail. It does seem like something that could be implemented in the future. The system is already super flexible.It would certainly be really neat to have full inheritance support for PushType::Node.

(Aaron Russell) #4

That makes sense actually - the fields you define in any class won’t be inherited by any descendants.

In that case, option 2 from above is your best bet, and then use a concern to share common fields:

module BlogEntry
  extend ActiveSupport::Concern
  included do
    field :description, :wysiwyg
    # ... etc

And include in to each relevant node:

class Article < PushType::Node
  include BlogEntry