わたしが今回投稿した理由
オンラインスクールで学んだことを活かしてその備忘録として今回執筆することにいたしました。
素人が書いているものなので、もし違っている内容があった場合はご容赦いただけると幸いです。
早速ですが、初めていきましょう。
開発環境
- rails 6
- データベース:postgresql(のちにherokuでデプロイさせたかったため)
- VSCode
- 今回はresourcesで使用
(これを使用したらshow,destroy,update,edit,index等を一括で定義できます)
コード
- ターミナルに以下を入力する
rails new 自分の作りたいアプリ名 -d postgresql
❇︎基本railsはSQLite3がデフォルトになっているので、-dとするとデータベースを指定することができる。
そのあと実行すること
-
自分が作ったアプリ名のフォルダに戻るような感じにする
例)cd my_favorite -
これが終わったら、ターミナルに以下を入力
rails db:create
- 自分で作ったアプリのフォルダを
VSCodeにドロップしてあげる。そうすると、VSCodeで編集できるようになる。
gem deviseをインストール
-
gemfileに以下を記述
gem 'devise'
- 追記が終了したら、以下をターミナルに入力
bundle install
gemがインストールできたら、deviseのログイン機能を実装するために必要なコマンドをターミナルに入力
rails g devise:install *(コロン忘れ注意)*
❇︎ なぜ、rails g devise:installなのかというと、deviseは専用のコマンドを使用し、
設定ファイルを作成する必要があるため、このようにする必要がある
devise専用モデルを作成するので、ターミナルに以下を入力
rails g devise user *(こっちはコロン不要)*
終了したあとは、以下のコマンドをターミナルに入力
rails db:migrate
次にナビゲーションバーを作成
-
application.html.erbに以下の記述をする
<!-- 略 -->
<body>
<!-- ここから書きます -->
<% if user_signed_in? %>
<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<%= link_to "トップ", products_path %>
<%= link_to "投稿画面へ", new_product_path %>
<% else %>
<%= link_to "ログイン", new_user_session_path %>
<%= link_to "新規登録", new_user_registration_path %>
<% end %>
<!-- ここまで書きます -->
<%= yield %>
</body>
</html>
ナビゲーションバーを実装したら、次はproductモデルとproductコントローラーを作成する
- 以下をターミナルに記述
rails g model product
- 上記を行なったら、
migrationfileの項目を以下のように編集する
- ここで、productsテーブルにname,price,user_idのカラムを作成するため、以下のように編集する。尚、user_idカラムは、ログインしたユーザーと紐付けるために必要
class CreateProducts < ActiveRecord::Migration[5.2]
def change
create_table :products do |t|
t.string :name
t.integer :price
t.integer :user_id
# ここまで
t.timestamps
end
end
end
上記を実行したあとは以下をターミナルで実行
rails db:migrate
- 上記が無事終了したら、
db/seeds.rbにてデータの編集を行う
Product.create(name: "Ruby入門", price: 2500, user_id: 1)
Product.create(name: "Rails基礎", price: 2900, user_id: 1)
Product.create(name: "PHP基礎", price: 1500, user_id: 1)
上記が終了したら、以下のコマンドをターミナルに入力
rails db:seed
これでエラーが発生しない場合は、テーブルに無事登録されている
無事に登録完了したら以下のコマンドをターミナルに入力
rails g controller Products *(頭文字大文字と複数にするように)*
コマンド入力後は以下のような処理を行う
-
config/routes.rbを以下のように編集
Rails.application.routes.draw do
root to: 'products#index'
resources :products
end
上記が終わったら、indexアクションを定義する
class ProductsController < ApplicationController
def index
@products = Product.all
end
end
indexアクションが定義できたら、次はこれに対応するviewファイルを作成
<h1>新規投稿一覧</h1>
<% if user_signed_in? %>
<% @products.each do |product| %>
<p>商品名:<%= product.name %></p>
<p>金額:<%= product.price %></p>
<% else %>
恐れ入りますが、ログインお願いします
<% end %>
<% end %>
-
deviseでログイン機能を実装すると、ログイン・サインアップ画面は自動的に生成されるがviews -
の中には該当するファイルが存在しない。そのため、今のままだとログイン画面に変更を加えることができない。
-
もし変更を加える場合は、
deviseのコマンドを利用してビューファイルを生成する必要がある。 -
ログイン画面用のビューファイルを生成するためには、以下のコマンドをターミナルに入力。
rails g devise:views
上記ができたら、次はproducts_controllerのnewアクションを定義
class ProductsController < ApplicationController
def new
@product = Product.new
end
end
ビューファイルの作成
- 上記までできたら、
usersディレクトリの中のnew.html.erbに新規投稿フォームを作成する
<h1>新規投稿</h1>
<%= form_with model: @product, local: true do |form| %>
<p>商品名:<%= form.text_field :name, required: true %></p>
<p>金額:<%= form.text_field :age, required: true %></p>
<%= form.submit "送信" %>
<% end %>
createアクションを定義
def create
Product.create(name: product_params[:name], price: product_params[:price],
user_id: current_user.id)
redirect_to root_path
end
createアクションが定義できたら、ストロングパラメータの登場!
products_controller下部に以下のように記述
<!-- 略 -->
private
def product_params
params.require(:user).permit(:name, :price)
end
- こちらを解説すると、
userモデルに紐づいた(:name, :price)のみ許可するよということを定義している
上記が終了したら、products_controllerの一番上に下記コマンドを記述
class ProductsController < ApplicationController
before_action :move_to_index, except: :index ←こちらを追加
def index
@products = Product.all
end
def new
@product = Product.new
end
def create
Product.create(name: product_params[:name], price: product_params[:price], user_id: current_user.id)
end
def move_to_index
redirect_to action: :index unless user_signed_in? ←こちらを追加
end
以下省略
これをアクションの前に書くとログインしていない場合には、その他のアクションにはいかず、indexアクションに強制的にいくようにする。
ルートを一部変更する
Rails.application.routes.draw do
root to: 'products#index'
resources :products
resources :users, only: :show ←これを追加
end
- 今回は、
users_controllerの中でもshowアクションしか使わないから、上記のように書く
usersコントローラーを新しく作ってあげるのでターミナルに以下を記述する
rails g controller Users
users_controllerに以下を記述
class UsersController < ApplicationController
def show
@products = Product.where(user_id: current_user.id)
end
end
show.html.erb(userscontrollerのビューファイル)に以下を記述
<% @products.each do |product| %>
<p>商品名:<%= product.name %></p>
<p>価格:<%= product.price %></p>
<% end %>
application.html.erbに以下の記述を追加で記入(ナビゲーションバー)
<!-- 略 -->
<% if user_signed_in? %>
<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<%= link_to "トップ", products_path %>
<%= link_to "投稿画面へ", new_product_path %>
<%= link_to 'マイページへ', user_path(current_user.id) %>
←これを追加
<% else %>
<%= link_to "ログイン", new_user_session_path %>
<%= link_to "新規登録", new_user_registration_path %>
<% end %>
購入商品一覧に購入したユーザーのIDを表示させるため、/views/productsのindex.html.erbに次のように書く
<h1>新規投稿一覧</h1>
<% if user_signed_in? %>
<% @products.each do |product| %>
<p>商品名:<%= product.name %></p>
<p>金額:<%= product.price %></p>
<p>会員No.:<%= product.user.id %></p>
<% else %>
恐れ入りますが、ログインお願いします
<% end %>
<% end %>
しかし、このままだとエラーが発生する。ここからどうしたらいいかというとアソシエーションという処理を実行する。
イメージとしてはuserとproductを結合させるようなイメージ
まず初めに行うこと
-
app/modelsにあるproduct.rbを以下のように編集
class Product < ApplicationRecord
belongs_to :user←こちらを記述
end
- 解説を行うとすると、
productは誰が持っているの?と考えたら、あ、ユーザーだという考えになるはずだから、
このように記述する
次に行うこと
-
app/modelsにあるuser.rbを以下のように編集
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 :products←こちらを記述
end
- 解説をすると、
userは、何をたくさん持ってるの?と考えたら、productsいっぱい持っているという考えになると
おもうから、このように記述する
これでアソシエーションが完了したので、2点改善を行なう。
まず1点目は、先ほど、users_controllerのshowアクションを記述したが、少し不格好なので、以下のように変更する
- 変更前
class UsersController < ApplicationController
def show
@products = Product.where(user_id: current_user.id)
end
end
- 変更後
def show
@products = User.find(current_user.id)
end
2点目は、show.html.erb (userscontroller)を以下のように変更
- 変更前
<% @products.each do |product| %>
<p>商品名:<%= product.name %></p>
<p>価格:<%= product.price %></p>
<% end %>
- 変更後
<% @user.products.each do |product| %>(←@user.productsに変更する)
<p>商品名:<%= product.name %></p>
<p>価格:<%= product.price %></p>
<% end %>
最後に
これでログイン機能の実装、crud処理の大まかなことはできました。
edit,updateアクションの実装、フラッシュ機能や、bootstrapで装飾等も説明したかった部分はありますが、今回はここまでにしておきます。
今後、ご自身のポートフォリオを作成する際、ログイン機能を実装するときは、最初にdeviseを実装してから、crud処理等を行なった方が、もしかしたら行き詰まりにくくなると思います。(私がそうでした笑)
ありがとうございました。