0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

crud処理、deviseを使った製作物について(初心者向け)

Last updated at Posted at 2020-08-28

わたしが今回投稿した理由

オンラインスクールで学んだことを活かしてその備忘録として今回執筆することにいたしました。
素人が書いているものなので、もし違っている内容があった場合はご容赦いただけると幸いです。
早速ですが、初めていきましょう。

開発環境

  • rails 6
  • データベース:postgresql(のちにherokuでデプロイさせたかったため)
  • VSCode
  • 今回はresourcesで使用
     (これを使用したらshow,destroy,update,edit,index等を一括で定義できます)

コード

  • ターミナルに以下を入力する
rails new 自分の作りたいアプリ名 -d postgresql

❇︎基本railsSQLite3がデフォルトになっているので、-dとするとデータベースを指定することができる。

そのあと実行すること

  • 自分が作ったアプリ名のフォルダに戻るような感じにする
    例)cd my_favorite

  • これが終わったら、ターミナルに以下を入力

rails db:create
  • 自分で作ったアプリのフォルダをVSCodeにドロップしてあげる。そうすると、VSCodeで編集できるようになる。

gem deviseをインストール

  • gemfileに以下を記述
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に以下の記述をする
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にてデータの編集を行う
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を以下のように編集
config/routes.rb
 Rails.application.routes.draw do
 root to: 'products#index'
 resources :products
 end

上記が終わったら、indexアクションを定義する

products_controller.rb
 class ProductsController < ApplicationController
  def index
   @products = Product.all
  end
 end

indexアクションが定義できたら、次はこれに対応するviewファイルを作成

index.html.erb
<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_controllernewアクションを定義

products_controller.rb
 class ProductsController < ApplicationController
  def new
   @product = Product.new
  end
 end

ビューファイルの作成

  • 上記までできたら、usersディレクトリの中のnew.html.erbに新規投稿フォームを作成する
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アクションを定義

products_controller.rb
 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下部に以下のように記述

products_controller.rb
<!--  -->
 private
  def product_params
   params.require(:user).permit(:name, :price)
  end
  • こちらを解説すると、userモデルに紐づいた(:name, :price)のみ許可するよということを定義している

上記が終了したら、products_controllerの一番上に下記コマンドを記述

products_controller.rb
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アクションに強制的にいくようにする。

ルートを一部変更する

routes.rb
 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に以下を記述

users_controller.rb
 class UsersController < ApplicationController
  def show
   @products = Product.where(user_id: current_user.id)
  end
 end

show.html.erbuserscontrollerのビューファイル)に以下を記述

show.html.erb
<% @products.each do |product| %>
  <p>商品名:<%= product.name %></p>
  <p>価格:<%= product.price %></p>
<% end %>

application.html.erbに以下の記述を追加で記入(ナビゲーションバー)

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/productsindex.html.erbに次のように書く

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 %>

しかし、このままだとエラーが発生する。ここからどうしたらいいかというとアソシエーションという処理を実行する。

イメージとしてはuserproductを結合させるようなイメージ

まず初めに行うこと

  • app/modelsにあるproduct.rbを以下のように編集
product.rb
 class Product < ApplicationRecord
  belongs_to :user←こちらを記述
 end
  • 解説を行うとすると、productは誰が持っているの?と考えたら、あ、ユーザーだという考えになるはずだから、
    このように記述する

次に行うこと

  • app/modelsにあるuser.rbを以下のように編集
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_controllershowアクションを記述したが、少し不格好なので、以下のように変更する

  • 変更前
users_controller.rb
 class UsersController < ApplicationController
  def show
   @products = Product.where(user_id: current_user.id)
  end
 end
  • 変更後
users_controller.rb
def show
 @products = User.find(current_user.id)
end

2点目は、show.html.erb (userscontroller)を以下のように変更

  • 変更前
show.html.erb
<% @products.each do |product| %>
  <p>商品名:<%= product.name %></p>
  <p>価格:<%= product.price %></p>
<% end %>
  • 変更後
show.html.erb
<% @user.products.each do |product| %>(←@user.productsに変更する)
  <p>商品名:<%= product.name %></p>
  <p>価格:<%= product.price %></p>
<% end %>

最後に

これでログイン機能の実装、crud処理の大まかなことはできました。
edit,updateアクションの実装、フラッシュ機能や、bootstrapで装飾等も説明したかった部分はありますが、今回はここまでにしておきます。
今後、ご自身のポートフォリオを作成する際、ログイン機能を実装するときは、最初にdeviseを実装してから、crud処理等を行なった方が、もしかしたら行き詰まりにくくなると思います。(私がそうでした笑)
ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?