Rails - has_many through, STI, and scope

Viewed 147

I have the following models:

    create_table :production_actions do |t|
      t.string :name
      t.string :key
    end

    create_table :production_attributes do |t|
      t.string :name
      t.string :key
      t.string :type
    end

    create_table :production_items do |t|
      t.timestamps
    end

    create_table :line_items_production_items do |t|
      t.references :line_item, null: false
      t.references :production_item, null: false
    end
    add_index(:line_items_production_items, [:line_item_id, :production_item_id], unique: true, name: 'line_items_production_items_unique')

    create_table :production_attributes_production_items do |t|
      t.references :production_attribute, null: false, index: {name: 'production_items_on_production_attribute_id'}
      t.references :production_item, null: false, index: {name: 'production_attributes_on_production_item_id'}
    end
    add_index(:production_attributes_production_items, [:production_attribute_id, :production_item_id], unique: true, name: 'production_attributes_production_items_unique')

    create_table :production_actions_production_items do |t|
      t.references :production_action, null: false, index: {name: 'production_items_on_production_action_id'}
      t.references :production_item, null: false, index: {name: 'production_actions_on_production_item_id'}
    end
    add_index(:production_actions_production_items, [:production_action_id, :production_item_id], unique: true, name: 'production_actions_production_items_unique')
  class ProductionAttributeProductionItem < ApplicationRecord
    belongs_to :production_attribute, class_name: "ProductionAttribute::Base"
    belongs_to :production_item, class_name: "ProductionItem::Base"
  end

  module ProductionItem
    class Base < ApplicationRecord
      self.table_name = "production_items"

      has_many :production_attribute_production_items, class_name: "ProductionAttributeProductionItem"
      has_many :production_attributes, class_name: "ProductionAttribute::Base", through: :production_attribute_production_items

  end

  module ProductionAttribute
    class Base < ApplicationRecord
      self.table_name = "production_attributes"


    end
  end
  module ProductionAttribute
    class PaperType < ProductionAttribute::Base

    end
  end
  module ProductionItem
    class Paper < ProductionItem::Base
              has_one :paper_type, -> { where(type: "ProductionAttribute::PaperType")},
                class_name: "ProductionAttribute::PaperType", foreign_key: :product_attribute_id,
                through: :production_attributes, inverse_of: :product_attribute

    end
  end

There are many types of production_items that are all saved in a table via STI. There are also many types of production_attributes all saved in a table via STI. A production_item has (and belongs to) many production_attributes. Based off the subclass, i want to create specific product_attribute associations based off the type of production_item. for instance, a paper production_item will have a paper_type product_attribute.

my problem is i am trying to get the specific scoped associations like paper.paper_type to work but i am having a hard time. If i do something like the following i get an error:

[1] pry(main)> p = ProductionItem::Paper.new
   (0.3ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
=> #<ProductionItem::Paper:0x00005602a669b528
 id: nil,
 created_at: nil,
 updated_at: nil>
[2] pry(main)> p.paper_type
ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) "paper_type" or :paper_type in model ProductionAttribute::Base. Try 'has_many :paper_type, :through => :production_attributes, :source => <name>'. Is it one of jobs?
from /home/USERNAME/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activerecord-5.2.4.4/lib/active_record/reflection.rb:920:in `check_validity!'

Ive tried a few things without any luck. any idea why this isnt working?

1 Answers

Did you store the foreign keys in the models that are in the database?

To use belongs_to, has_many and has_one you need to store these values in some way in the database.

For example, in ProductionItem you don't necessarily need to store the ids of other objects (it would be interesting, but it would be something similar to an array). But if you decide not to do this above, you must save the id of each ProductionItem in the object that belongs to it.

Related