はじめに
・前回の記事はこちら↓
商品を売ったり買ったりする場合にclass_nameを使ってみた
https://qiita.com/fishmans0120/items/5b40fb2a057e4d722a67
・備忘録として書いています。
・間違いなどあればご指摘いただけますと幸いです。
今回の前提条件とゴールについて
・usersテーブルがある
・itemsテーブルがある
・商品を売ったり買ったりすると仮定する
・中間テーブルはつくらない
・seller_idにログインユーザーのidが表示される←ここをゴールにします
さっそくミニアプリを作ってみます
$ rails _6.0.0_ new class_name_app -d mysql
railsのバージョンを6.0.0に指定して、
class_name_appという名前のアプリケーションを、
データベースMySQLで、
生成します。
$ cd class_name_app/
ディレクトリを移動しました。
ユーザーを生成するためと、haml記法を使うためにgemをインストールします。
gem `devise`
gem `haml-rails`
$ bundle install
これでdeviseとhaml-railsが使えるようになりました。
データの保存形式を変更します。
# encoding: utf8mb4
encoding: utf8
データベースを生成しましょう。
$ rails db:create
ではitemsテーブルを作っていきます。
$ rails g model item
class CreateItems < ActiveRecord::Migration[6.0]
def change
create_table :items do |t|
# 商品名を入力するためにstring型でnameカラムを作成します
t.string :name
t.timestamps
end
end
end
$ rails db:migrate
これでitemsテーブルができました。
nameカラムがstring型で追加されています。
次にusersテーブルを作ります。
$ rails g devise:install
$ rails g devise user
$ rails db:migrate
$ rails haml:erb2haml
この順で入力してください。
usersテーブルができあがります。
サインアップ、ログイン、ログアウトもできるようになりました。
最後のコマンドは現在erb記法で記述されているファイルをhaml記法に変換するコマンドです。途中で入力を求められたらy
を入力してください。
なお、今回はusersテーブルにユーザー名を表示させるnameカラムを作っていません。 必要であれば追加してください。
itemsコントローラーを生成して、ルーティングも設定します。
class ItemsController < ApplicationController
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
redirect_to new_item_path
else
render 'new'
end
end
private
def item_params
params.require(:item).permit(:name).merge(seller_id: current_user.id)
end
end
Rails.application.routes.draw do
devise_for :users
resources :items
root 'items#new'
end
ビューファイルはこのようにします。
%h1 Items#new
%p Find me in app/views/items/new.html.haml
.logout
= link_to "ログアウト", destroy_user_session_path, method: :delete
.login
= link_to "ログイン", new_user_session_path, class: "post"
.signup
= link_to "新規登録", new_user_registration_path, class: "post"
.form
= form_with model: @item, local: true do |f|
= f.text_field :name
= f.submit "送信"
ざっくり言うと、
・newアクションで新規入力し、createアクションでデータを新規登録する
・ちゃんとセーブできたらnew画面へリダイレクト、セーブできなかったらnew画面へデータそのままで戻る
・localhost:3000へアクセスしたら自動的にnew画面になりますよ
・ログアウトボタンを押すとログインしてない状態になります
・ログインボタンを押すとログイン画面に遷移します
・新規登録ボタンを押すとサインアップ画面に遷移します
・商品名を入力して送信ボタンを押すとテーブルにデータが保存されます
こんな感じです。でもまだやることが残っています。
モデルファイルに追記しましょう。
class Item < ApplicationRecord
belongs_to :buyer, class_name: "User", foreign_key: "buyer_id", optional: true
belongs_to :seller, class_name: "User", foreign_key: "seller_id"
end
ここ大事!!!
Rails 5.1からの変更点として、belongs_toを指定した時、自動的にrequired: trueオプションが追加されpresenseのバリデーションが走るようになったようです(https://github.com/rails/rails/issues/34454 )。
そのため、今回のケースではbuyer_idのほうにoptional: trueをかけてpresenseのバリデーションを追加しないように指定する
ことが必要です。
こうしないとユーザー新規登録時と購入時にbuyerを入力してくださいと言われちゃいます。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :bought_items, class_name: 'Item', foreign_key: 'buyer_id'
has_many :sold_items, class_name: 'Item', foreign_key: 'seller_id'
end
class_nameの記述をしました。
仕組みについては前回の記事を見てください。
itemsテーブルにseller_idカラムとbuyer_idカラムをinteger型で追加します。
$ rails g migration AddColumnToItems
class AddColumnToItems < ActiveRecord::Migration[6.0]
def change
add_column :items, :seller_id, :integer
add_column :items, :buyer_id, :integer
end
end
$ rails db:migrate
これでカラムが追加されました。
ではデータベースを起動してみましょう。
$ rails s
ブラウザでlocalhost:3000
にアクセスしてください。
こんな画面になっているかと思います。
まずは新規登録でユーザーを作成してください。
その後、入力フィールドに商品名を入力して送信を押すと、テーブルにデータが保存されるはずです。
sequelProなどでテーブルの中身を見ると、seller_idのところにログインしているユーザーのidが入っていると思います。(僕はid:2
のユーザーでログインしていたのでseller_id:2
になっています)
おわりに
ここまでの流れで問題がなければ、開発環境で実装できるのではないかと思います。
備忘録として書いていますが、以下少しだけ。
僕は新しいことを実装する前には簡単なミニアプリを作ってから実装するようにしているのですが、頭の整理にもなってていいなと思っています。
まだまだ初学者の域を抜けませんが、他の方の助けになりましたら幸いです。
ありがとうございました。