商品出品機能実装
実装概要
- 商品出品機能を実装する。
- モデルの単体テストコードを書く。
Itemモデルを作成
ターミナル
rails g model item
マイグレーションファイルの修正
マイグレーションファイルをDB設計に基づいて下記に修正
/db/migrate/2024~_create_items.rb
class CreateItems < ActiveRecord::Migration[7.0]
def change
create_table :items do |t|
t.string :name, null: false
t.text :description, null: false
t.integer :category_id, null: false
t.integer :status_id, null: false
t.integer :shipping_fee_id, null: false
t.integer :prefecture_id, null: false
t.integer :delivery_time_id, null: false
t.integer :price, null: false
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
マイグレーションの実行
ターミナル
% rails db:migrate
アソシエーションの記述
app/models/user.rb
has_many :items
app.models/item.rb
belongs_to :user
必要なルーティングを記述
/config/routes.rb
resouces :items, only: [:index, :new]
画像投稿機能を実装
ImageMagickをインストール
ターミナル
brew install imagemagick
Gemをインストール
Gemfile
# Gemfileの一番下に記述する
gem 'mini_magick'
gem 'image_processing', '~> 1.2'
ターミナル
bundle install
設定を変更
画像処理にMiniMagickを使用するため、設定ファイルに記述を行う。
/config/application.rb
module Furima41457
class Application < Rails::Application
中略
config.active_storage.variant_processor = :mini_magick
中略
end
end
ローカルサーバーを再起動
ターミナル
% rails s
Active Storageをインストール
ターミナル
% rails active_storage:install
rails active_storage:installコマンドを実行すると、Active Storageに関連したマイグレーションが作成される。続けてマイグレートする。
ターミナル
% rails db:migrate
Itemsテーブルに画像ファイルを紐付ける
下記ファイルに画像ファイルのアソシエーションを追記
app/models/item.rb
has_one_attached :image
画像の保存を許可するストロングパラメーターにする
app/controllers/items_controller.rb
#中略
private
def message_params
permitted_attributes = [:name, :image, :description, :category_id, :status_id, :shipping_fee_id, :prefecture_id, :price]
params.require(:item).permit(*permitted_attributes).merge(user_id: current_user.id)
end
end
カラムが多いので、見通しを良くするために配列を使用して管理していく。
ActiveHashを導入
ターミナル
#中略
gem 'active_hash'
ターミナル
% bundle install
Activehashで使用するモデルをそれぞれ作成
app/modelsディレクトリ配下にカラム名に沿ったファイル名を命名
app/models/category.rb
class Category < ActiveHash::Base
self.data = [
{ id: 1, name: '---' },
{ id: 2, name: 'メンズ' },
{ id: 3, name: 'レディース' },
{ id: 4, name: 'ベビー' },
{ id: 5, name: 'キッズ' },
{ id: 6, name: 'インテリア・住まい・小物、本・音楽・ゲーム' },
{ id: 7, name: 'おもちゃ・ホビー・グッズ' },
{ id: 8, name: '家電・スマホ・カメラ' },
{ id: 9, name: 'スポーツ・レジャー' },
{ id: 10, name: 'ハンドメイド' },
{ id: 11, name: 'その他' }
]
end
app/models/status.rb
class Status < ActiveHash::Base
self.data = [
{ id: 1, name: '---' },
{ id: 2, name: '新品・未使用' },
{ id: 3, name: '未使用に近い' },
{ id: 4, name: '目立った傷や汚れなし' },
{ id: 5, name: 'やや傷や汚れあり' },
{ id: 6, name: '傷や汚れあり' },
{ id: 7, name: '全体的に状態が悪い' }
]
end
app/models/shipping_fee.rb
class ShippingFee < ActiveHash::Base
self.data = [
{ id: 1, name: '---' },
{ id: 2, name: '着払い(購入者負担)' },
{ id: 3, name: '送料込み(出品者負担)' }
]
end
app/models/prefecture.rb
class Prefecture < ActiveHash::Base
self.data = [
{ id: 1, name: '---' },
{ id: 2, name: '北海道' },
{ id: 3, name: '青森県' },
{ id: 4, name: '岩手県' },
{ id: 5, name: '宮城県' },
{ id: 6, name: '秋田県' },
{ id: 7, name: '山形県' },
{ id: 8, name: '福島県' },
{ id: 9, name: '茨城県' },
{ id: 10, name: '栃木県' },
{ id: 11, name: '群馬県' },
{ id: 12, name: '埼玉県' },
{ id: 13, name: '千葉県' },
{ id: 14, name: '東京都' },
{ id: 15, name: '神奈川県' },
{ id: 16, name: '新潟県' },
{ id: 17, name: '富山県' },
{ id: 18, name: '石川県' },
{ id: 19, name: '福井県' },
{ id: 20, name: '山梨県' },
{ id: 21, name: '長野県' },
{ id: 22, name: '岐阜県' },
{ id: 23, name: '静岡県' },
{ id: 24, name: '愛知県' },
{ id: 25, name: '三重県' },
{ id: 26, name: '滋賀県' },
{ id: 27, name: '京都府' },
{ id: 28, name: '大阪府' },
{ id: 29, name: '兵庫県' },
{ id: 30, name: '奈良県' },
{ id: 31, name: '和歌山県' },
{ id: 32, name: '鳥取県' },
{ id: 33, name: '島根県' },
{ id: 34, name: '岡山県' },
{ id: 35, name: '広島県' },
{ id: 36, name: '山口県' },
{ id: 37, name: '徳島県' },
{ id: 38, name: '香川県' },
{ id: 39, name: '愛媛県' },
{ id: 40, name: '高知県' },
{ id: 41, name: '福岡県' },
{ id: 42, name: '佐賀県' },
{ id: 43, name: '長崎県' },
{ id: 44, name: '熊本県' },
{ id: 45, name: '大分県' },
{ id: 46, name: '宮崎県' },
{ id: 47, name: '鹿児島県' },
{ id: 48, name: '沖縄県' }
]
end
app/models/delivery_time.rb
class DeliveryTime < ActiveHash::Base
self.data = [
{ id: 1, name: '---' },
{ id: 2, name: '1~2日で発送' },
{ id: 3, name: '2~3日で発送' },
{ id: 4, name: '4~7日で発送' }
]
end
モデルとの関連付けおよびバリデーションの設定
モデルでActiveHashを使用するために、Itemモデルに以下のように関連付け・バリデーションを追記
app/models/item.rb
#中略
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to :category
belongs_to :status
belongs_to :shipping_fee
belongs_to :prefecture
belongs_to :delivery_time
validates :category_id, numericality: { other_than: 1, message: "can't be blank" }
validates :status_id, numericality: { other_than: 1, message: "can't be blank" }
validates :shipping_fee_id, numericality: { other_than: 1, message: "can't be blank" }
validates :prefecture_id, numericality: { other_than: 1, message: "can't be blank" }
validates :delivery_time_id, numericality: { other_than: 1, message: "can't be blank" }
各Activehashモデルにアソシエーションを追記
app/models/Activehashモデル名
include ActiveHash::Associations
has_many :items
それぞれ使用したいActivehashモデルに対応した表示がされるようにビューファイル修正
app/views/items/new.html.erb
#中略
<%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"select-box", id:"item-category"}) %>
#中略
Itemモデル作成からActiveStorageを使用した画像投稿機能の実装とActivHashを使用したカテゴリーの選択ができる機能の実装までをまとめてみました。
次回はJavascriptを使用して実装を行なっていきます。