わたしが今回投稿した理由
オンラインスクールで学んだことを活かしてその備忘録として今回執筆することにいたしました。
素人が書いているものなので、もし違っている内容があった場合はご容赦いただけると幸いです。
早速ですが、初めていきましょう。
開発環境
- 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処理
等を行なった方が、もしかしたら行き詰まりにくくなると思います。(私がそうでした笑)
ありがとうございました。