Search code examples
ruby-on-railsrubyassociationsstiruby-on-rails-5

Association between two STI/Polymorphic


Currently I have a Group and GroupPeriod that contains the same attributes

  create_table "groups", force: :cascade do |t|
    t.bigint "company_id"
    t.string "name"
    t.date "cutoff_date"
    t.date "processing_date"
    t.integer "working_days"
    t.integer "working_hours"
    t.integer "status"
    t.float "basic_pay"
    t.string "type"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["company_id"], name: "index_groups_on_company_id"
  end

  create_table "group_periods", force: :cascade do |t|
    t.bigint "company_id"
    t.date "start_date"
    t.date "end_date"
    t.string "type"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.bigint "group_id"
    t.index ["company_id"], name: "index_group_periods_on_company_id"
    t.index ["group_id"], name: "index_group_periods_on_group_id"
  end

The logic is Group has many GroupPeriods. But then I have different groups; Bill and Pay. So I'm creating an STI for both BillGroup and PayGroup:

class Group < ApplicationRecord
  has_many :group_periods
end

class BillGroup < Group
  #=> has_many :bill_periods??
end

class PayGroup < Group
  #=> has_many :pay_periods??
end

The issue I'm having is that each group will have many PayPeriod or BillPeriod. So I created a GroupPeriod to link

class GroupPeriod < ApplicationRecord
  belongs_to :group
end

class BillPeriod < GroupPeriod
  #=> belongs_to :bill_group??
end

class PayPeriod < GroupPeriod
  #=> belongs_to :pay_group??
end

My question is, how can I ensure through inheritance, I can be flexible that

  1. BillGroup has many BillPeriods;
  2. PayGroup has many PayPeriods;

without overlapping (BillGroup will not see PayPeriod and vice versa) with each other? At the same time, is this a bad practice that I should make them into 2 different tables for each BillGroup and PayGroup?


Solution

  • class Group < ApplicationRecord
      has_many :group_periods
    end
    
    class Period < ApplicationRecord
      belongs_to :group
      belongs_to :group_periods, polymorphic: true
    end
    
    class BillPeriod < GroupPeriod
      has_many :periods, as: :group_periods, dependent: :destroy
    end
    
    class PayPeriod < GroupPeriod
      has_many :periods, as: :group_periods, dependent: :destroy
    end
    

    your model looks something like this , rest depends on your associations.