とまとの成長日記

ぴよぴよエンジニアの日々学んだとこを投稿。時々、ゆるーくすきなもの・趣味について語ってます。

gem sorcery使ってみた

アカウント系のgemだとよくdeviceを見かけるのですが、現場だとsorceryをよく使うらしいので早速チャレンジしていきましょう💪
誤りなどがたくさん出てきそうな予感なので、ご指摘、ご指導よろしくお願いいたします🙇‍♀️🙇‍♀️
※間違いがあったため、修正中です(2019/07/15)

gem sorcery を gemfile に追加
#Gemfileにsorcery追加
$ gem 'sorcery'
$ bundle install
#sorceryで必要な初期ファイルをインストール
$ bundle exec rails generate sorcery:install
$ rake db:migrate


参考までに、db:migrate後のマイグレーションファイルを載せておきます。

class SorceryCore < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :email,            null: false
      t.string :crypted_password
      t.string :salt

      t.timestamps                null: false
    end

    add_index :users, :email, unique: true
  end
end

また、今回、last_name と first_nameを分けたいのでカラム追加します。

$ bundle exec rails g migration AddNameToUsers last_name:string first_name:string
$ bundle exec rails db:migrate

カラム追加完了!

※気をつける点はこの時点ではUsersControllerを作ってないのでこれから作っていきます。
sorceryのgitだとscaffoldの書き方が書いてあるのですが、今回は勉強のため、controller、viewは自分で書いていきます!
sorceryに書いてあるやり方と異なる点がたくさん出てきていますのでご注意ください!!

UsersControllerを作る
$ bundle exec rails g controller users new create
ルーティングを設定

今回なるべくシンプルにルーティングを書きたかったため、必要最低限のルーティング設定にしています。

Rails.application.routes.draw do
  root 'static_pages#index'
  resources :users, only: [:create]

  get '/signup', to: 'users#new'
  get '/login', to: 'user_sessions#new'
  post '/login', to: 'user_sessions#create'
end

まず、ここでは説明していないですが、トップページを作りたかったため、StaticPagesControllerを作っています。

resourcesではUsersControllerのcreateアクションのみ設定しています。
他の部分は、urlを指定したかったので個別に書いています。


これでコードを書いていく準備完了です
ここからの大まなか流れをざっくりと説明します。
まず、ユーザーを新規登録するための準備をいろいろやります。
その後、ユーザーがログインするためにいろいろやります。
では、そのいろいろを説明していきます!

新規登録ブロック

privateメソッドを指定しよう!
class UsersController < ApplicationController
private
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, :last_name, :first_name)
  end
end

privateメソッドの中のメソッドは、外部のオブジェクトに対して提供する意志のないメソッドということになります。
つまり、UsersControllerクラス以外には提供しないよー!ってことです。

ユーザーが入力した値を受け取りましょう!

単に入力してきた値を受け取っています!笑
users/new.html.erb

<h1>新規登録</h1>
<div class="row">
  <div class="col-md-6 offset-md-3">
    <%= form_for(@user) do |f| %>
    <%= f.label :email %>
    <%= f.email_field :email, class: 'form-control' %>

    <%= f.label :password %>
    <%= f.password_field :password, class: 'form-control' %>

    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, class: 'form-control' %>

    <%= f.label :last_name %>
    <%= f.text_field :last_name, class: 'form-control' %>

    <%= f.label :first_name %>
    <%= f.text_field :first_name, class: 'form-control' %>

    <%= f.submit class: "btn btn-primary" %>
  <% end %>
  <%= link_to "ログイン", login_path, class: 'col-md-6 offset-md-3'%>
</div>

Validationをかけましょう!
class User < ApplicationRecord
  authenticates_with_sorcery!
  validates :last_name, presence: true
  validates :first_name, presence: true
  validates :email, presence: true, uniqueness: true
  validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }
end

そもそも、なんでValidationをかけるのかというと、正しいデータだけを保存するためです!

では、それぞれ見ていくと
last_name, first_name → 値が入っているかどうか
email → 値が入っているかどうかと値が重複していなかどうか
password → パスワードのミニマムの長さ指定と2つのテキストフィールドで受け取る内容が完全に一致しているかどうか
password_confirmation → 値が入っているかどうか

ユーザー情報を保存しましょう!

先程入力した値を正しい情報で受け取ることができるようになったのでデータベースに保存しましょう!

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to login_path
    else
      render :new
    end
  end
end

user#newアクションでUser.newでUserを作るための箱を用意します。
user#createアクションで@userにuser_paramsで入ったデータを箱にいれます。
@user.saveでデータを保存します。
保存が成功したら、ログインページへ行きます。
保存が失敗したら、もう一度登録画面へ行きます。
redirect_toとrenderの違いは過去に記事でまとめているので興味があればみてください〜
renderとredirect_toの違い - とまとの成長日記

これで登録はできるようになります!実際の画面をみていきましょう!!
新規登録画面です。
情報を入力して登録ボタンを押します。
f:id:toomeeto:20190715024057p:plain

ログはこんな感じで出ます!
無事保存され、ログイン画面にリダイレクトされています!
f:id:toomeeto:20190715024158p:plain

ログインブロック

UserSessionsControllerを作りましょう!
$ be rails g controller UserSessions new create
ログインに必要なデータを受け取りましょう!

user_sessions/new.html.erb

<h1>ログイン</h1>
<div class="container">
  <div class="row">
    <div class="col-md-6 offset-md-3">
      <%= form_for(:user_sessions) do |f| %>
      <%= f.label :email,(t '.email') %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password,(t '.password') %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.submit "ログイン", class: "btn btn-primary" %>
    <% end %>
    <div class="row">
      <%= link_to "新規登録", signup_path , class: 'col-md-6'%>
    </div>
    </div>
  </div>
</div>

これでデータを受け取る準備完了です!

ログインできるようにUserSessionsControllerを書いていく

ここではログインに関することを書いていきます!
では、中身を書いていきます!

class UserSessionsController < ApplicationController
 def new
  end

  def create
    user = login(params[:user_sessions][:email], params[:user_sessions][:password])
    if user
      redirect_to root_url
    else
      render :new
    end
  end
end

UserSessions#createで@userにparamsで入力された値を受け取ります。
ログインに成功したら、トップページへ行きます。
ログインに失敗したら、ログインページに戻ります。

早速ログインしてみましょう!
ログイン画面に値を入力して
f:id:toomeeto:20190715025021p:plain

ログはこんな感じです!
無事トップページへいくURLが動いています
f:id:toomeeto:20190715025054p:plain


はい、今回もざっくりとした説明でした。笑
また、情報は修正・追記していきますので、よろしくお願いします!

感想

過去最長の記事になりましたあああああ
頑張って書いた。自分で褒めておく😭💗