anywhereseason
anywhereseason

Reputation: 233

Rails: Select all Children models of Parent and sort by date created in Active Record

In my rails app, I am trying to select all of the child models ( ‘pdfs’ ‘videos’ ‘infographics’ ) which have a reference to a parent model (‘category’). These three child models can belong to only one of three parent models (this is enforced using an Exclusive arc validation in the child models). So they have a one in three chance of belonging my parent model (‘category’).

Is there a way of selecting all of the children models ( ‘pdfs’ ‘videos’ ‘infographics’ ), which are attached to my specific parent model (‘category’)? If i am able to do this, is it possible to sort each of these instances of the children models by the date they were created? And finally, would I be able to have this ordered list of children instances as an array, so that I can iterate over it in the view?

Thank you for your help! Model set up below.

The parent model:

class Category < ApplicationRecord
  belongs_to :navbar_base_folder
  has_many :sub_categories, dependent: :destroy
  has_many :infographics, dependent: :destroy
  has_many :videos, dependent: :destroy
  has_many :pdfs, dependent: :destroy
end

The three children:

class Pdf < ApplicationRecord
  belongs_to :sub_category, optional: true
  belongs_to :category, optional: true
  belongs_to :secret_category, optional: true
  belongs_to :secret_sub_category, optional: true
end

class Video < ApplicationRecord
  belongs_to :sub_category, optional: true
  belongs_to :category, optional: true
  belongs_to :secret_category, optional: true
  belongs_to :secret_sub_category, optional: true
end

class Infographic < ApplicationRecord
  belongs_to :sub_category, optional: true
  belongs_to :category, optional: true
  belongs_to :secret_category, optional: true
  belongs_to :secret_sub_category, optional: true
end

Upvotes: 0

Views: 464

Answers (1)

Patrick C
Patrick C

Reputation: 186

This is a perfect candidate for single table inheritance (STI).

class Category < ApplicationRecord
  has_many :contents, dependent: :destroy
  has_many :infographics
  has_many :pdfs
  has_many :videos
end

# db/migrate/create_content.rb
# Create a migration for Content
  create_table :content do |t|
    # .... add your attributes here ...
    t.string :type, index: true
  end
end

# app/models/content.rb
class Content < ApplicationRecord
  belongs_to :category
  # `has_many ... optional: true` is not invalid, but you should aim to
  # keep your associations & validations separate. Instead put this as a
  # validation:
  validates :category, presence: true
end

# app/models/pdf.rb
class Pdf < Content; end

# app/models/infographic.rb
class Infographic; end

# app/models/video.rb
class Video < Content; end

Then find all content:

@category = Category.first
@contents = @category.contents.order(date: :desc)

Hope that helps :)

P.S: Your Category should be refactored to a parent/child pattern if possible:

class Category < ApplicationRecord
# app/models/category.rb
# Your `Category` table should be using a `parent_id` column, not creating a "sub_category" model.
  belongs_to :parent_category, foreign_key: :parent_id, class_name: 'Category'
  has_many :sub_categories, foreign_key: :parent_id, class_name: 'Category'
  attribute :is_secret, Boolean
end

Upvotes: 1

Related Questions