Episodes

Resources

Download Source Code

Summary

# Terminal
rails g scaffold brand name
rails g scaffold product brand:references name 'price:decimal{5,2}'
rails db:migrate
rails db:seed
rails routes

# Gemfile
gem 'faker'

# db/seeds.rb
10.times do
  Brand.create do |brand|
    brand.name = Faker::Company.name
    100.times do
      brand.products.new do |product|
        product.name = Faker::Commerce.product_name
        product.price = Faker::Commerce.price
      end
    end
  end
end

# models/brand.rb
class Brand < ApplicationRecord
  has_many :products, dependent: :destroy
end

# models/product.rb
class Product < ApplicationRecord
  belongs_to :brand #, optional: true

  scope :cheap_products, -> { where(price: 0..50.00).order(price: :asc) }
  # scope :expensive_products, -> { where(price: 50.01..Float::INFINITY).order(price: :asc) }
  scope :expensive_products, -> { where(price: 50.01..1.0/0.0).order(price: :asc) }
  
  # def self.cheap_products
  #   where(price: 0..50.00).order(price: :asc)
  # end
end

# config/routes.rb
Rails.application.routes.draw do
  resources :brands do
    resources :products
  end
end

# products_controller.rb
class ProductsController < ApplicationController
  before_action :set_brand, except: [:index]
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  def index
    @brand = Brand.includes(:products).find(params[:brand_id])
    @products = @brand.products
  end

  def show
  end

  def new
    @product = @brand.products.new
  end

  def edit
  end

  def create
    @product = @brand.products.new(product_params)

    if @product.save
      # redirect_to brand_product_path(@brand, @product), notice: 'Product was successfully created.'
      redirect_to [@brand, @product], notice: 'Product was successfully created.'
    else
      render :new
    end
  end

  def update
    if @product.update(product_params)
      redirect_to [@brand, @product], notice: 'Product was successfully updated.'
    else
      render :edit
    end
  end

  def destroy
    @product.destroy
    # redirect_to brand_products_path(@brand), notice: 'Product was successfully destroyed.'
    redirect_to [@brand, :products], notice: 'Product was successfully destroyed.'
  end

  private
    def set_brand
      @brand = Brand.find(params[:brand_id])
    end
    
    def set_product
      @product = @brand.products.find(params[:id])
    end

    def product_params
      params.require(:product).permit(:brand_id, :name, :price)
    end
end

# products/_form.html.erb
<%= form_with(model: [@brand, product], local: true) do |form| %>

# products/_product.html.erb
<tr>
  <td><%= product.name %></td>
  <td><%= product.price %></td>
  <td><%= link_to 'Show', [@brand, product] %></td>
  <td>
    <%# link_to 'Edit', edit_brand_product_path(@brand, product) %>
    <%= link_to 'Edit', [:edit, @brand, product] %>
  </td>
  <td><%= link_to 'Destroy', [@brand, product], method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>