はじめに
管理者側から商品を投稿して顧客の商品一覧ページに表示させます。
ステータスはenumで実装しました。
bootstrap導入済み
devaice導入済み
migrateファイルはこんな感じ
class CreateItems < ActiveRecord::Migration[6.1]
def change
create_table :items do |t|
t.string :name, null: false
t.text :description, null: false
t.integer :price, null: false
t.boolean :is_active, null: false, default: true
t.timestamps
end
end
end
モデルの設定
class Item < ApplicationRecord
has_one_attached :image
enum status: { on_sale: 0, off_sale: 1 }
end
has_one_attached :image
は、Active Storage(Railsのファイルアップロードを担当する部分)に対する指示で、各Itemレコードが一つのimageファイルを持つことを示しています。
enum status: { on_sale: 0, off_sale: 1 }
は、statusという名前の列があることを示しています。status列は整数型で、on_saleが0、off_saleが1としてマッピングされます。これにより、Itemの状態を文字列ではなく整数でデータベースに保存でき、それによりパフォーマンスを向上させ、コード内で直感的にその状態を理解できます。
コントローラの設定
class Admin::ItemsController < ApplicationController
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
redirect_to admin_items_path
else
render :new
end
end
private
def item_params
params.require(:item).permit(:name, :description, :price, :status, :image)
end
end
newアクション
新規Itemオブジェクトを作成し、それを@itemというインスタンス変数に代入します。このアクションは、新規作成フォームの表示を担当します。
createアクション
フォームからのデータ(パラメータ)を用いて新規Itemオブジェクトを作成します。作成が成功した場合、商品一覧ページ(admin_items_path)にリダイレクトします。失敗した場合は、新規作成フォームを再度表示します。
item_params
ストロングパラメータ(Strong Parameters)と呼ばれる機能を使用して、フォームから送信されたデータのうち、どのデータを許可するか(受け取るか)を指定しています。これは、不正なデータを防ぐためのセキュリティ機能です。
private
は、その下に定義されたメソッドがプライベート(このクラスの内部からのみアクセス可能)であることを示します。これにより、他の部分から直接これらのメソッドを呼び出すことはできません。
veiws 商品投稿ページ
<h3 class="text-center">商品新規登録</h3>
<%= form_with model: [:admin, @item], local: true, class: 'col-6 mx-auto' do |f| %>
<div class="form-group row">
<%= f.label :image, '商品画像', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9">
<%= f.file_field :image, class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<%= f.label :name, '商品名', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9">
<%= f.text_field :name, class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<%= f.label :description, '商品説明', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9">
<%= f.text_area :description, class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<%= f.label :price, '税抜価格', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9 input-group">
<%= f.number_field :price, class: 'form-control' %>
<div class="input-group-append">
<span class="input-group-text">円</span>
</div>
</div>
</div>
<div class="form-group row">
<%= f.label :status, '販売ステータス', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9">
<div class="custom-control custom-radio custom-control-inline">
<%= f.radio_button :status, 'on_sale', checked: @item.status == 'on_sale', class: 'custom-control-input', id: 'status-on-sale' %>
<%= f.label :status, '販売中', class: 'custom-control-label', for: 'status-on-sale' %>
</div>
<div class="custom-control custom-radio custom-control-inline">
<%= f.radio_button :status, 'off_sale', checked: @item.status == 'off_sale', class: 'custom-control-input', id: 'status-off-sale' %>
<%= f.label :status, '販売停止中', class: 'custom-control-label', for: 'status-off-sale' %>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-9 offset-sm-3">
<%= f.submit '新規投稿', class: 'btn btn-success text-white' %>
</div>
</div>
<% end %>
販売ステータスについて
<div class="form-group row">
<%= f.label :status, '販売ステータス', class: 'col-sm-3 col-form-label' %>
<div class="col-sm-9">
上記の部分はブートストラップのクラスを使用してレイアウトを作成しています。:statusは商品のステータス(販売中か販売停止中か)を示す属性です。
<div class="custom-control custom-radio custom-control-inline">
<%= f.radio_button :status, 'on_sale', checked: @item.status == 'on_sale', class: 'custom-control-input', id: 'status-on-sale' %>
<%= f.label :status, '販売中', class: 'custom-control-label', for: 'status-on-sale' %>
</div>
この部分では、on_sale(販売中)というステータスを設定するラジオボタンを作成しています。
@item.status == 'on_sale' という部分は、商品の現在のステータスがon_sale であれば、このラジオボタンが選択されるようにしています。
<div class="custom-control custom-radio custom-control-inline">
<%= f.radio_button :status, 'off_sale', checked: @item.status == 'off_sale', class: 'custom-control-input', id: 'status-off-sale' %>
<%= f.label :status, '販売停止中', class: 'custom-control-label', for: 'status-off-sale' %>
</div>
</div>
</div>
最後の部分は販売停止(off_sale)のステータスを設定するラジオボタンを作成しています。
@item.status == 'off_sale' という部分は、商品の現在のステータスが off_sale であれば、このラジオボタンが選択されるようにしています。
このように、管理者は商品のステータスを選択して、商品が販売中か販売停止中かを設定することができます。これらの設定はItemモデルの:status属性に保存されます。
補足
このエラーは、Active Storageが適切にセットアップされていないことを示しています。Active Storageは、Railsでファイルアップロードを処理するためのフレームワークです。具体的には、active_storage_blobsテーブルがデータベースに存在しないために発生しています。
エラーメッセージにあるように、以下のコマンドを実行してActive Storageをセットアップし、必要なテーブルを作成します。
$ bin/rails active_storage:install
このコマンドを実行すると、必要なマイグレーションファイルが作成されます。その後、以下のコマンドを実行してマイグレーションをデータベースに適用します。
$ bin/rails db:migrate
これにより、Active Storageが適切に機能します