[Ruby] Creating an EC site with Rails5 ⑧ ~Product model edition, conditionally narrowed down display for both parent and child~

3 minute read

Introduction

This is a continuation of the series Create an EC site with Rails 5 ⑦, a series for creating an EC site where you can shop at a fictitious bakery. This time, it is an implementation of the Product model that displays the product list and details. Since the management of the product is done on the admin site side, only the process of displaying the screen on the customer site side is required.

However, both the Genre model that bundles products and the Product model that belongs to it have the status of “On Sale/Stop”. This means that you can set the same for each genre in addition to setting whether to stop or sell each product. It is a little difficult to narrow down because it is only valid for both Genre and Product on the customer site.

Source code

https://github.com/Sn16799/bakeryFUMIZUKI

Model Association

fumizuki_ER.jpg

controller

app/controllers/products_controller.rb


class ProductsController <ApplicationController

  # For sidebar display
  before_action :set_genres

  def show
    @product = Product.find(params[:id])
    @cart = @product.cart_items.build
  end

  def index
# Filter products with valid genre and valid product status
    @products = Product.includes(:genre).where(genres: {validity: true}).is_active.page(params[:page]).per(9)
  end

  private

  def set_genres
    @genre = Genre.is_valid
  end

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

In the index, conditions are set in the validity column of the Genre model (parent) and the status column of the Product model (child) to narrow it down. With this, it is possible to retrieve the product group of “Genre is valid” and “Product status is valid”. We also have a pager (kaminari) so that 9 items can be displayed on each page.

app/models/product.rb


scope :is_active, -> {where(status: true)}

app/models/genre.rb


scope :is_valid, -> {where(validity: true)}

Both is_active and is_valid in the controller are scopes for narrowing the valid/invalid of products and genres. Since this application is not a process to be performed many times, it is not particularly required, but defining a scope makes it easier to modify later, what kind of process is being done on the code source, It will be easier to understand.

view

index screen

html:app/views/products/index.html.erb


<div class="col-lg-10 space">
  <div class="container">
  <h2>
    <span style="display: inline-block;">List of all products</span>
    <span style="display: inline-block;"> (<%= @products.count %> seed) </span>
  </h2>
</div>
  <div class="container">
    <div class="row">
    <% @products.each do |gp| %>
      <%= render'products/box', product: gp %>
    <% end %>
  </div>
  </div>
  <%= paginate @products %>
</div>
<%= render'genres/index', genres: @genres %>

In the partial template,’products/box’ is a small div that shows photos, names, prices, etc. for each product, and’genres/index’ is a sidebar with links to view products by genre. HTML source is previous article.

show screen

html:app/views/products/show.html.erb


<div class="col-lg-10 space">
  <div class="container">
    <div class="row">
      <div class="col-lg-4 offset-lg-2">
        <%= attachment_image_tag(@product, :image, :fill, 560, 420, fallback: "no_img.jpg") %>
      </div>
      <div class="col-lg-4">
        <h3>
          <%= @product.name %>
        </h3>
        <h4>Product description</h4>
        <%= @product.introduction %>
        <h4>
          <%= price_include_tax(@product.price) %>
        </h4>
      </div>
    </div>
  </div>

  <div class="container">
    <div class="w-50 offset-lg-6">
    <%= form_with(model: [@product, @cart], local: true, url: {controller:'cart_items', action:'create'}) do |f| %>
    <%= f.label: Purchased quantity %>
    <%= f.number_field :quantity, value: 1 ,min:1, max:99 %>
    <%= f.hidden_field :product_id, value: @product.id %>
    <%= f.submit "Add to cart", class: "btn btn-danger" %>
    <% end %>
  </div>
  </div>
</div>

<%= render'genres/index', genres: @genres %>

On the show screen, you can see the description of the item and add it to your cart.

It is designed to display a blank form, but since nothing has been written in CartItemController, an error will occur when the “Add to cart” button is pressed at this time. Please note.

Postscript

By making a screen with many products lined up, it became a bakery site. As usual, there are no functional aspects. In addition, the pager and product box have not been subjected to CSS processing at all, so it is not possible to wipe off the feeling of being a bit deadly. The decorations are planned to be done at the end, so I’d like to hurry to complete the function first.

The prototype of this EC site is an app made by the team implementation of the school, but when I look at it now, there are places where it is unexpectedly missing such as validation. I thought that there was something that I missed even if three people worked together, but maybe it was not just an issue with requirements defined in detail.

This is the second development, so I would like to stick to that area as well. Continue to Next time!

Reference

I want to search from Rails small model with parent model information