rails で中間テーブルを使いたくて、RailsApplicationBuild Guidesを参考に構築しました。
コードは、上記のgithubを使っています。
1.4.3. サンプルアプリケーション
テーブル構成
以下の三つです。
- product テーブル
- categoryテーブル
- product_categoryテーブル
挙動
投稿フォームからデータを入れて登録ボタンを押したら無事に反映されていたのですが、データベースを確認したところ、中間テーブルにデータが保存されていませんでした
。
保存されていたのはproduct でした。
model
productテーブル
# == Schema Information # # Table name: products # 商品 # # id :integer not null, primary key # code :string(10) not null # 商品コード # name :string(50) not null # 商品名 # name_kana :string(50) default(""), not null # 商品名カナ←削除 # price :integer not null # 商品価格←削除 # purchase_cost :integer not null # 仕入原価←削除 # availability :boolean not null # 販売可能フラグ←削除 # created_at :datetime not null # updated_at :datetime not null # class Product < ApplicationRecord has_many :product_categories has_many :categories, through: :product_categories accepts_nested_attributes_for :product_categories, allow_destroy: true validates :code, presence: true, length: { maximum: 10 } validates :name, presence: true, length: { maximum: 50 } end
categoryテーブル
# == Schema Information # # Table name: categories # カテゴリ # # id :integer not null, primary key # name :string(50) not null # カテゴリ名 # created_at :datetime not null # updated_at :datetime not null # class Category < ApplicationRecord has_many :product_categories has_many :products, through: :product_categories end
ProductCategoryモデル 中間テーブル
# == Schema Information # # Table name: product_categories # 商品カテゴリ # # id :integer not null, primary key # product_id :integer not null # 商品ID # category_id :integer not null # カテゴリID # created_at :datetime not null # updated_at :datetime not null # class ProductCategory < ActiveRecord::Base belongs_to :product belongs_to :category end
**
form/product.rb**
class Form::Product < Product # == Schema Information # # Table name: products # 商品 # # id :integer not null, primary key # code :string(10) not null # 商品コード # name :string(50) not null # 商品名 # name_kana :string(50) default(""), not null # 商品名カナ # price :integer not null # 商品価格 # purchase_cost :integer not null # 仕入原価 # availability :boolean not null # 販売可能フラグ # created_at :datetime not null # updated_at :datetime not null # REGISTRABLE_ATTRIBUTES = %i(code name) has_many :product_categories, class_name: 'Form::ProductCategory' end
form/product_category.rb
# # Table name: product_categories # 商品カテゴリ # # id :integer not null, primary key # product_id :integer not null # 商品ID # category_id :integer not null # カテゴリID # created_at :datetime not null # updated_at :datetime not null # class Form::ProductCategory < ProductCategory REGISTRABLE_ATTRIBUTES = %i(id product_id category_id _destroy) def selectable_categories Category.all end end
view
view/products/new このページから商品情報を登録します。
ここに言語を入力 <% content_for(:title) do %> 商品登録 <% end %> <%= render 'form', path: products_path, method: :post %>
view/products/_form
<div class="panel panel-default"> <div class="panel-body"> <div class="row"> <div class="col-sm-12"> <%= form_for(@product, url: path, method: method) do |f| %> <div class="col-sm-6"> <div class="form-group"> <label class="control-label" for="">商品コード</label> <%= f.text_field :code, class: 'form-control' %> </div> <div class="form-group"> <label class="control-label" for="">商品名</label> <%= f.text_field :name, class: 'form-control' %> </div> </div> <div class="col-sm-12"> <hr> <b>商品カテゴリ</b> <div class="text-right"> <%= link_to_add_association 'カテゴリを追加', f, :product_categories, class: 'btn btn-default', data: { association_insertion_node: '#detail-association-insertion-point', association_insertion_method: 'append' } %> </div> <table class="table table-list"> <thead> <tr> <th></th> <th></th> </tr> </thead> <tbody id='detail-association-insertion-point'> <div class="form-group"> <%= f.fields_for :product_categories do |od| %> <%= render 'product_category_fields', f: od %> <% end %> </div> </tbody> </table> </div> <div class="col-sm-12"> <div class="text-center"> <%= f.submit '登録', class: 'btn btn-primary' %> </div> </div> <% end %> </div><!-- /col-sm-12 --> </div><!-- /row --> </div><!-- /panel-body --> </div><!-- /panel --> ※商品コード、商品名以外は省いています。
view/products/index 登録後このページで表示されます。
<% content_for(:title) do %> 商品検索 <% end %> <% @products.each do |product| %> <li><%= product.name %></li> <% end %> ※元のコードでは商品を検索して表示させるものでしたが、ransakなどのgemインストールが必要でしたので検索機能は省いてます。登録したものだけ表示するようにしています。
view/products/_product_category_fields.html.erb
<tr class="nested-fields"> <%= f.hidden_field :id %> <td> <%= f.collection_select :category_id, f.object.selectable_categories, :id, :name, {}, class: 'form-control' %> </td> <td> <%= link_to_remove_association '削除', f, class: 'btn btn-default' %> </td> </tr>
controller
products_controller.rb
class ProductsController < ApplicationController def index # @q = Product.search @products = Product.all end def new @product = Form::Product.new end def edit @product = Form::Product.find(params[:id]) end def create @product = Form::Product.new(product_params) if @product.save redirect_to products_path, notice: "商品 #{@product.name} を登録しました。" else render :new end end def update @product = Form::Product.find(params[:id]) if @product.update_attributes(product_params) redirect_to products_path, notice: "商品 #{@product.name} を更新しました。" else render :edit end end private def search_params search_conditions = %i(code_cont name_cont) params.require(:q).permit(search_conditions) end def product_params params .require(:form_product) .permit( Form::Product::REGISTRABLE_ATTRIBUTES + [product_categories_attributes: Form::ProductCategory::REGISTRABLE_ATTRIBUTES] ) end end def search がありましたがこちら消してます。
routes.rb
resources :products do collection do get :search end end # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html end
schema
ActiveRecord::Schema.define(version: 2022_02_05_121124) do create_table "categories", force: :cascade do |t| t.string "name" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "product_categories", force: :cascade do |t| t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.integer "product", null: false t.integer "category", null: false t.integer "product_id", null: false t.integer "category_id", null: false t.index ["category_id"], name: "index_product_categories_on_category_id" t.index ["product_id"], name: "index_product_categories_on_product_id" end create_table "products", force: :cascade do |t| t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "code" t.string "name" end add_foreign_key "product_categories", "categories" add_foreign_key "product_categories", "products" end
コードは以上になります。
上記の通りに書き込むとproductテーブルに書き込まれてしまいます。
中間テーブルに書き込みたいのですがどのようにすればよいでしょうか?
どなたか中間テーブルに詳しい方教えていただけますでしょうか?
よろしくお願いいたします(__)
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/02/07 13:26
2022/02/08 06:52