Search code examples
ruby-on-railsmodelcontrollerhas-and-belongs-to-manyjoin

Rails HABTM setup, model object, & join_table insertion controller setup


I have the following setup.

1 product has many product_types. many product_types have 1 type. A HABTM relationship from my understanding of the docs.

My models are

class Product < ApplicationRecord
  has_and_belongs_to_many :types
end

class Type < ApplicationRecord
  has_and_belongs_to_many :products
end

I have a join table migration as such

class CreateJoinTableProductTypes < ActiveRecord::Migration[5.1]
  def change
    create_join_table :products, :types do |t|
      t.index :product_id
      t.index :type_id
    end
  end
end

I have created a form - hopefully created correctly where now I have the following parameters being sent on form submit:

"product"=>{"name"=>"Product A", "description"=>"A cool product", "image_dir_path"=>"./",
"type"=>{"id"=>"1"}},"commit"=>"Create Product"}

I'm wondering 1) what is the best/rails convention for submitting the parameters for creating the product in the form and controller?

and

2) how are/do I get, the records inserted into the join table?

I have the following method for getting the params

def product_params
  params.require(:product).permit(:name, :description, :image_dir_path, :type,)
end

but even then I can see in the logs unpermitted parameter for :type

at the moment my controller only has:

@product = Product.new(product_params)

I would greatly appreciate any advice on the rails way of creating this object. I've read the api docs for HABTM but don't see anything when it comes to the model object or how I should be handling this stuff in the controller.

Thanks!


Solution

  • After max's comment I realised Type relationship wasn't a HABTM but was a one to many with product. I had another model Size that was in a HABTM with Product though.

    My Models look like this:

    class Product < ApplicationRecord
      belongs_to :product_type
      has_and_belongs_to_many :sizes
    end
    
    class Size < ApplicationRecord
      has_and_belongs_to_many :products
    end
    

    Join table is:

    class CreateJoinTableProductSize < ActiveRecord::Migration[5.1]
      def change
        create_join_table :cakes, :sizes do |t|
          t.index [:product_id, :size_id]
        end
      end
    end
    

    Size table is default Product table is

    class CreateProducts < ActiveRecord::Migration[5.1]
      def change
        create_table :products do |t|
          t.string :name
          t.string :description
          t.references :product_type, foreign_key: true
    
          t.timestamps
        end
      end
    end
    

    My controller is the default - I just have the following params whitelisted

    def cake_params params.require(:product).permit(:name, :description, :product_type_id, {:size_ids=>[]}) end

    My _form has the following

      <div class="field">
        <%= form.label :product_type_id %>
        <%= form.collection_select(:product_type_id, ProductType.all, :id, :name) %>
      </div>
    
      <div class="field">
        <%= form.label :product_size %>
        <%= collection_check_boxes(:product, :size_ids, Size.all, :id, :name) %>
      </div>
    

    Now I can submit the form, edit it and all values are displayed correctly!