Reputation: 592
I have Products and Books. I'm trying to connect Books to a Product with collection_select
Here's part of my product form:
<%= f.label :book_id %><br>
<%= f.collection_select(:book_id, Book.all, :id, :title, {}, multiple: :true) %>
Book Model:
class Book < ActiveRecord::Base
belongs_to :product
end
Product Model:
class Product < ActiveRecord::Base
has_many :books
end
Migrations:
class AddBookToProducts < ActiveRecord::Migration
def change
add_column :products, :book_id, :integer
add_index :products, :book_id
end
end
class AddProductToBooks < ActiveRecord::Migration
def change
add_column :books, :product_id, :string
add_index :books, :product_id
end
end
BooksController:
def new
@book = Book.new
authorize @book
end
def create
@book = Book.new(book_params)
@book.user = current_user
...
ProductsController:
class ProductsController < ApplicationController
require "stripe"
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
@products = Product.all.page params[:page]
authorize @products
end
# GET /products/1
# GET /products/1.json
def show
@stripe_btn_data = {
key: "#{ Rails.configuration.stripe[:publishable_key] }",
description: @product.title,
amount: (@product.price * 100),
}
authorize @product
end
# GET /products/new
def new
@product = Product.new
@books = Book.all
authorize @product
end
# GET /products/1/edit
def edit
authorize @product
end
# POST /products
# POST /products.json
def create
@product = Product.new(product_params)
authorize @product
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
authorize @product
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: @product }
else
format.html { render :edit }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
@product.destroy
authorize @product
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :body, :price, :active, :state, :hardcopy_book, :online_only, :online_hardcopy, :expiration, :monthly, :annual, :user_id, :book, :book_id, :id)
end
end
Parameters show the :book_id but it does not insert the book_id into products.
Here's how I am showing the selected books on the product/show
<strong>Book:</strong>
<ul>
<% @product.books.each do |book| %>
<li><%= link_to book.tile, (book) %><li>
<% end %>
</ul>
What am I missing?
Upvotes: 0
Views: 68
Reputation: 11275
Firstly, your migration is wrong, we only need one migration and here it is:
class AddBookToProducts < ActiveRecord::Migration
def change
add_column :books, :product_id, :string
add_index :books, :product_id
end
end
Because Book belongs to Product and Product has many Book so add one column product_id
to Books table is enough.
Secondly, edit your Product form to: (please note the change from book_id
to book_ids
)
<%= f.label :book_id %><br>
<%= f.collection_select(:book_ids, Book.all, :id, :title, {}, multiple: :true) %>
Then add book_ids
to Strong parameter in ProductsController
def product_params
params.require(:product).permit(:title, :body, :price, :active, :state, :hardcopy_book, :online_only, :online_hardcopy, :expiration, :monthly, :annual, :user_id, :book, :id, :book_ids => [])
end
Upvotes: 1