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

♀尐吖头ヾ 提交于 2020-08-06 05:46:28

问题


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!


回答1:


ActieRecord generates _ids setters and getters for all has_many and has_and_belongs_to_many associations.

# creates 3 rows in products_types if they do not exist
# also deletes any rows not in the array
@product.update(type_ids: [1,2,3])

These are used together with the form options helpers to assign associations:

<%= form_for(@product) do |f| %>
  <div class="field">
    <%= f.label :type_ids %>
    <%= f.collection_select :type_ids, Type.all, :id, :name, multiple: true %>
  </div>
  ...
<% end %>

To whitelist the param you pass it as a option with the value [] which permits an array containing any scalar type.

def product_params
  params.require(:product).permit(:name, :description, :image_dir_path, type_ids: [])
end

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

With the has_and_belongs_to_many association you can only insert/access rows indirectly.

For example by:

@product.types 
# or
@product.types << Type.first
# or
@product.types.create(name: 'Foo')

Or by using the type_ids setter/getter previously mentioned. This is a key difference from has_many through: where you have a join model that can be queried or created directly.




回答2:


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!



来源:https://stackoverflow.com/questions/49847418/rails-habtm-setup-model-object-join-table-insertion-controller-setup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!