sk

開発で得たこと

チュートリアル ~ プログラミング独学者に向けて教材を用意しました ~

現場のノウハウを盛り込んだチュートリアルを作成しました。

対象読者

ある程度コードを理解したつもりだけど、 現場に挑戦するのは自信がないなぁという人向けです。

これをやると何がいいのか

現場のコードをかけるようになります。 私が独学でプログラミングを学習していた時は現場とはかけ離れたコードを書いていました。

ネットには技術記事は落ちていますが、 どれが現場で使われているのか知るすべがありません。

私が現場で書いているコードをチュートリアルにしてみなさんにご提供できればなと思います。

進め方

チュートリアルではチケット予約サービスを扱っています。 メインの記事を中心に作業をしていただきます。

ところどころにコラムやポイントとして、 リンクを貼っていますのそちらにもぜひ着手して学習してください。

目次

【bundlerまとめ】bundle installの--path vendor/bundleって何?

f:id:sksksksksk:20180728162228p:plain

結論

bundle install --path vender/bundle

vender/bundle 配下にgemをインストールします。

アプリケーションごとにgemをインストールすることができるので、システムに依存しないアプリケーションを構築することができます。 複数アプリケーションがローカルPC内に存在する場合や複数人と開発を行う際に役に立ちます。

プロジェクト管理の必要性について

現場では一つのアプリケーションだけを管理・開発することはまずありません。 個人でRailsアプリケーションを開発している人はそれだけでローカルPC内に複数のアプリケーションが存在します。

gemはRailsアプリケーションごとに管理することもローカルPC内で管理することもできます。 ローカルPCのgemはそれぞれこれまでにインストールしてきたgemがあります。みんなローカルPCにあるgemは同じでないです。

ローカルPCでgemを管理して作業をしてしまうと、私のPCではアプリケーションが動作するがあの人のPCでは動作しないという現象が起きてしまいます。 個々人の開発環境に左右されず、アプリケショーンを正常に動作させる必要があります。

bundlerって何?

アプリケーションプロジェクト内で使用するパッケージ管理システムです。

bundlerを使うことでアプリケーションプロジェクトごとにgemを管理することができます。 同じようなものにrbenvが挙げられます。 rbenvはgemではなく、rubyのバージョンをアプリケーションごとに管理します。

どうして--path vendor/bundle をつけるの?

--path vendor/bundle をつけることでアプリケーションにgemをインストールすることができます。

具体的にはvender/bundle配下にgemがインストールされるようになります。

f:id:sksksksksk:20180728163829p:plain

実例

  • 実行
$ bundle install --path vender/bundle
  • vendor/bundle配下にgemがインストールされる f:id:sksksksksk:20180728160635p:plain

  • Project/.bundle/configにパスが設定される

Project/.bundle/config

---
BUNDLE_PATH: vendor/bundle
BUNDLE_DISABLE_SHARED_GEMS: '1'

bundle execって何?

アプリケーションにインストールされたgemでアプリケーションを実行することができます。

例えばRailsサーバーを起動する時にrails sを実行するとシステムのgemを元にサーバーを起動し、 bundle exec rails s を実行するとアプリケーションのgemを元にサーバーを起動します。

bundle installのオプションまとめ

構文

bundle install --path <フォルダ名>

システム(PC)にインストール

bundle install

Railsアプリケーションにインストール

bundle install --path vendor/bundle

本番用以外のgemをインストール

bundle install --without production

開発・テスト環境以外のgemをインストール

bundle install --without development test

参考

Bundler: The best way to manage a Ruby application's gems

Bundler: The best way to manage a Ruby application's gems

プログラミングを1から独学で勉強してフリーランスになるまで - 独学編

私がFラン大学4年生から独学でプログラミングを勉強してフリーランスになるまでの道のりをまとめてみました。

今、プログラミングを勉強してIT企業にエンジニアとして就職したい学生、そのまま起業してしまいたい人、プログラマーは高給と聞いてキャリアチェンジを目標に勉強している社会人の皆さまの参考に少しでもなれば嬉しいです。

なんでプログラミングを勉強した?

  • ITってかっこよくてすごく魅力的だったから。
  • IT分野で起業したかったから。

ITってかっこいいですよね。 かっこいいからモテるし。IT起業家の浮いたお話もよく耳にします。(最近だとZOZOTOWNとか、showroom)

何よりみんな知らないことを知ってて作れて、 未来を作ってく先駆者みたいなイメージを持ってました。

プログラミングいつ始めた?

大学2年の夏

最初に手をつけたのは大学2年生だったのを覚えてます。Javaで簡単な冒険(ドラクエみたいな)ゲームを作るチュートリアルでした。 買ったばかりのでかいWindowsのノートパソコンで開発していましたが、すぐに挫折しました。

NetBeansチュートリアルのコードを写経して実行して。 周囲に相談できる人もいませんでしたし、チュートリアルも個人が作ったものでしたし。エラーをググるとかそういう発想も皆無でした。

prog-8.com

railstutorial.jp

大学4年の8月

就活時に、就職しないで起業したくて、面接の合間に隣に座ってた就活生に「起業したいんだけど投資家知ってる?」みたいなことを聞いてました。笑 聞き込みの甲斐がありまして、1人投資家を紹介してもらえることに。

その投資家に自分の事業案をプレゼンすると、僕の事業案には見向きもされず、 「とりあえず、プログラミングやってみたら?」と投資家に言われたのが、本格的にプログラミングを勉強し始めたきっかけです。

何を勉強した?

色々やりました。言語で言えば、RubyRailsJavaScriptJavaPython・Kotlin・PHP・Node.js。 ただ、なんとか使えるのはRubyRailsだけです。

何を勉強した?(もっと具体的に)

2016年8月

巷で話題のProgateをしました。 RubyRailsを新宿の就活カフェでひたすらに。

ある程度、コードが理解できるようになったら無料で配布されてるRailsチュートリアルを2~3周くらいしました。

2016年9月

ここら辺でもう「自分のサービス作りたいよぉ〜お願い〜」みたいな心理状態に移ったので自分のサービスを作り始めます。 今なら絶対に選ばないであろう、動画サービスを開発し出します。

ここから11月くらいまで大学にも行かず、 おきたらコード書いて、朝飯食って食器洗って、コード書いて昼食挟んで食器洗って、コード書いて晩飯食って風呂入ってコード書いて寝るという寝食と食器洗いとお風呂以外はプログラミングに時間を費やしました。

Qiita・teratail・stack over flowは必須でした。

qiita.com

teratail.com

ja.stackoverflow.com

2016年11月下旬

自分で開発したサービスが完成しました。当時はめちゃめちゃ評価高かったので(自分の中で)、以前からご厚意にさせてもらってるIT社長さんにみていただくことに。 夜にセブンの前に停めた車の中で。

そこで社長さんからも評価をいただき(サービスじゃなくて一人でよく頑張ったことに対して)育ててもらえることになります。 ここで、内定をもらっていた会社に辞退の旨を伝えます。(一応もらってました。)

2016年12月

その会社では速報系メディアを運営していて、 僕はその速報の元ネタを外部サイトから抽出するシステムを開発します。

学んだこと→ クロール技術を身につけました。また、データベースの接続やサービス運用の心得(サービスを担当するものの責任と姿勢)のようなものも学びます。これまではRubyRailsの違いすら理解していない状態でしたが、.rbだけでコードを書く機会が増え、フレームワークとの区別できるようになります。その社長さんは独学でプログラミングを学びインフラにも明るい人でした。やはり、自分よりも技術力ある人からコードレビューをもらったり、教えてもらえる方が何倍も学習効率が高いです。可能であれば、インターンやバイトでここらを経験できるといいかもしれませんね。

後で使用した技術書を載せておきます。

2017年1 ~ 7月

ここの期間はあまり社長から仕事をもらえませんでした。

暇でしたのでサービスを作っては潰すというのを繰り返してました。

この途中の3月には、PGColonyを通して知り合った次元のエンジニアにインフラ周りを5000円/月で教わりました。 PGColonyは今はサービス停止してるので使うことはできません。

2017年7月下旬

このままでは起業どころか、生活すら危ういと思い仕事を探しました。 ここで、僕の中で進路は正社員として働くか、フリーで働くかの2択でした。

結果的には、フリーランスとして働くことになり現在に至ります。 フリーランスになるまでの具体的な過程は プログラミングを1から独学で勉強してフリーランスになるまで - フリーランス編 - 現場の開発 でお話します。

総括

独学期間は約1年です。個人的にはものすごく自信になりました。 プログラミングは学習難易度が高いです。特に初期は無知なのに環境構築を行わなければならず、一人で超えるには高い壁です。 その条件下でフリーランスになるまで技術力をあげられたのは大きく、今後も何か課題を提示された時に活かせるのではないかと思います。

金銭面でも助かりました。必要最低限のコストで学習を進めることができました。 これがプログラミングスクールに通うという選択肢をとってしまうと非常に高額なお金を用意しなければなりません。

通うお金があるなら通ってもいいかもしれません。 しかし、スクールも手取り足取り教えてくれる訳ではなくほとんど独習です。

場所と教材費にお金をかけているようなもので、あまりコスパはよくないというのが正直な感想です。 最近は、独習できるサービスも多く立ち上がってるので、独学で行ってみるのもありかもしれませんね。

もっとも効率的なのはインターンかバイトです。 教えてもらえてお金がもらえますので。

以上で、プログラミングを1から独学で勉強してフリーランスになるまで - 独学編 は終了です。 これからプログラミングを学ぶ人、学んでいる人のお力になれることを願っております。

フリーランス編もあるので興味ある人はチェックしてみてください。

www.sendai-freelance.com

プログラミングを1から独学で勉強してフリーランスになるまで - フリーランス編

独学でプログラミングを勉強して約1年のエンジニアがどうやってフリーランスになったのかをお伝えします。

プログラミングを1から独学で勉強してフリーランスになるまで - 独学編 - さがえもん の続きです。

なんでフリーランスを選んだ?

当時、私は24歳で無職の起業家志望でした。 家庭の事情もあり私はなるべく早く起業をしてお金がたくさん入る立場にならなければなりませんでした。

新卒の社員で何年もかけて、給料をもらって自分の生活だけ支えることはできなかったのです。 そこで、社員より報酬が高く、比較的離脱しやすいフリーランスを選択しました。

どんなフリーランス

私の場合は、準委任契約のフリーランスです。企業に常駐して規定の時間働くと報酬をいただけます。 側からみたら正社員の方と同じ扱いに見えます。

正社員と働き方の違いは?

基本的には同じですが、私の企業の場合はディレクション業務や設計などの工程を行うことはありません。 全て、社員の方が行います。私が行うのはコードを書くことそれのみです。

シンプルにコードを書きたい方はこのポジションはしっくりくると思います。

企業のメリットは?

高い報酬をフリーランスに支払って、フリーランスはコードを書くだけって何かメリットあるのでしょうか? あります。エンジニアのフリーランスで言えば、技術のアウトソースをすることになります。

もし、このフリーランス全然コード書けないじゃん、と判断された場合、企業は契約を更新しません。 企業はこのように対応することで技術力のあるエンジニアだけを抱えることができます。

正社員の場合は、何か理由があったとしても解雇に値する理由でない限り社員を切ることはできません。 採用は企業にとってとても重要で、使えない社員を採用してしまうと人件費だけがドボドボ流れていってしまいます。

社会人経験なし、現場経験なしでフリーランスになるには?

結論からいうと結構難しいです。 私の場合はいろんなことが恵まれていました。

エージェントに登録する

最初にエージェントに登録しました。5~6社くらい登録しました。 その中でレスポンスが早かった2つのエージェントをメインに常駐先企業を探しました。

【Prosheet】 Prosheetは先日、ランサーズに買収されました。 プロシート(PROsheet) | フリーランス向け週2日〜のお仕事紹介。

【identity】 マッチング案件情報サイト - braineer freelance(ブレイナーフリーランス) | フリーランスのためのIT業界に特化した案件サイト

登録したらすぐにSkypeやら電話でヒアリングを受けます。 すぐに企業を紹介するから東京へ来てくれと言われました。

当時、宮城にいたのですが次の日には東京へ向かっていた覚えがあります。 そこから、東京で企業との面談を数社とって来てくれました。

最終的に、教育もしてくれる受託開発に決めて契約をしました。 サービスに登録してから契約が決まるまで1週間しかかかりませんでした。

私の場合は、運よく常駐先が見つかりましたが、 面談時に技術力がないのを見破られて渋い顔をされたりすることも往々にしてあります。

さらに、私と同時期にフリーランスとして契約した社員もいましたが、 その方も私とほぼ同じバックグラウンドで、契約を3ヶ月で切られました。

初歩的な質問が多かったことと、その人はリモートでコミュニケーションを取りづらい状況だったため 開発業務が思うように進んでいないのが原因だったようです。

最後に

こうしてなんとかフリーランスとして働けるようになったわけですが、 最初はそこそこ大変でした。

まず、フリーランスですから一般的にすでにある程度コードはかけるものだと思われます。 しかし、私の場合は全くついていけず時間外も働くことも。

3ヶ月で納品予定のサービスを私は5ヶ月かけてしまい大変迷惑をおかけしてしまうなど、 契約先には頭が上がりません。( ・3・;)~♪

ですが、なんとか食いついて今は少しはできるようになっています。 報酬面では、私と同世代の人の2倍はいただいていると思います。

記事を読んでくれている方も魅力的にうつっていればぜひフリーランスを選択してみてください!

使ったエージェント

prosheet.jp

freelance.braineer.jp

https://freelance.levtech.jp

routing(ルーティング)まとめ

リソースをネストさせる

Railsのリソースデータは原則 https://ドメイン名/リソース1名/リソース1のid という形式にするのが望ましいです。

悪い例 https://ドメイン名/tickets/deliveries/new?ticket_id=1

良い例 https://ドメイン名/tickets/1(ticket_id)/deliveries/new

このURLを生成するためには以下のようにresourcesをネストさせる必要があります。

resources :tickets do
  resources :deliveries, only: %i(new)
end

生成されるURL

/tickets/:ticket_id/deliveries/new(.:format)

予約機能の作成

この記事で行うこと

ユーザーがチケットを予約できるようにする。

使うもの

Ruby 2.4.2 Rails 5.1.6

前提

ユーザーの作成 - さがえもんを完了していること。

実装手順

① チケットの表示

チケット一覧をトップページに表示します。 チケットはログインしているユーザーもログインしていないユーザーも見ることができます。

welcome_controller.rb

class WelcomeController < ApplicationController
  def index
    @tickets = Ticket.all
  end
end

app/views/welcome/index.html.haml

.col-md-12
  %h3.text-center チケット一覧
  %table.table
    %thead
      %tr
        %th
        %th チケット名
        %th 内容
        %th.text-center チケット販売可能枚数
        %th.text-center 締切日
    %tbody
      - @tickets.each.with_index(1) do |ticket, index|
        %tr
          %td= index
          %td= ticket.title
          %td= ticket.body
          %td.text-center= ticket.number
          %td.text-center= ticket.expired_at

f:id:sksksksksk:20180727202507p:plain

② 予約とユーザーの関連付け

ユーザーはチケットを複数予約することができます。 ユーザーとチケットの中間モデルを予約が行うのでモデルの関係性は以下のようになります。

f:id:sksksksksk:20180727204522p:plain ER図の書き方

まず予約(Delivery)を作成します。

$ rails g model Delivery
Running via Spring preloader in process 35173
      invoke  active_record
      create    db/migrate/20180727113318_create_deliveries.rb
      create    app/models/delivery.rb
      invoke    test_unit
      create      test/models/delivery_test.rb
      create      test/fixtures/deliveries.yml

ユーザー・予約・チケットを関連付けします。

app/models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  # -------------------------------------------------------------------------------
  # Relations
  # -------------------------------------------------------------------------------
  has_many :deliveries, dependent: :destroy
end

app/models/ticket.rb

class Ticket < ApplicationRecord
  # -------------------------------------------------------------------------------
  # Relations
  # -------------------------------------------------------------------------------
  has_many :deliveries, dependent: :destroy
end

app/models/delivery.rb

class Delivery < ApplicationRecord
  # -------------------------------------------------------------------------------
  # Relations
  # -------------------------------------------------------------------------------
  belongs_to :user
  belongs_to :ticket  
end

db/migrate/20180727113318_create_deliveries.rb

class CreateDeliveries < ActiveRecord::Migration[5.1]
  def change
    create_table :deliveries do |t|
      t.belongs_to :user, foreign_key: true
      t.belongs_to :ticket, foreign_key: true
      t.timestamps
    end
  end
end

マイグレートコマンドを実行しましょう。

$ rails db:migrate
== 20180727113318 CreateDeliveries: migrating =================================
-- create_table(:deliveries)
   -> 0.0059s
== 20180727113318 CreateDeliveries: migrated (0.0059s) ========================

これで関連付けは終了です。

③ 確認画面

ユーザーがチケットを予約ボタンまで辿りつけるようにします。

チケット一覧画面に「予約する」ボタンを設置しましょう。 この「予約する」ボタンを押すと確認画面に遷移します。

Deliveryコントローラーを作成します。 Userスコープで作成しましょう。

$ rails g controller Users::Deliveries
Running via Spring preloader in process 35321
      create  app/controllers/users/deliveries_controller.rb
      invoke  haml
      create    app/views/users/deliveries
      invoke  test_unit
      create    test/controllers/users/deliveries_controller_test.rb
      invoke  helper
      create    app/helpers/users/deliveries_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users/deliveries.coffee
      invoke    scss
      create      app/assets/stylesheets/users/deliveries.scss

予約はログインユーザーしかできない仕様ですので、未登録・未ログインユーザーにはログインを強制します。 ログインリダイレクトのコールバックを作成しますが、今後予約以外でもログインしてほしい場面が出てくると思うので共通化しておきます。

BaseコントローラーをUserスコープに作成します。

$ rails g controller Users::Base
Running via Spring preloader in process 35374
      create  app/controllers/users/base_controller.rb
      invoke  haml
      create    app/views/users/base
      invoke  test_unit
      create    test/controllers/users/base_controller_test.rb
      invoke  helper
      create    app/helpers/users/base_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users/base.coffee
      invoke    scss
      create      app/assets/stylesheets/users/base.scss

baseコントローラーのコールバックにdeviseのauthenticate_user!を置きます。 app/controllers/users/base_controller.rb

class Users::BaseController < ApplicationController
  before_action :authenticate_user!
end

DeliveryコントローラーはこのBaseコントローラーを継承することで、 before_action :authenticate_user! を使用できるようになります。(AppricationController -> Users::BaseController

app/controllers/users/deliveries_controller.rb

class Users::DeliveriesController < Users::BaseController
end

これで、未登録・未ログインユーザーにはログインを強制することができるようになりました。

続いて、確認画面を作成していきましょう。

app/controllers/users/deliveries_controller.rb

class Users::DeliveriesController < Users::BaseController
  def new
    @ticket = Ticket.find(params[:ticket_id]) #チケット情報を確認画面で表示するため
  end
end

app/views/users/deliveries/new.html.haml

.col-md-12
  %h3.text-center 予約確認画面
  %table.table
    %thead
      %tr
        %th チケット名
        %th 内容
        %th.text-center チケット販売可能枚数
        %th.text-center 締切日
    %tbody
      %tr
        %td= @ticket.title
        %td= @ticket.body
        %td.text-center= @ticket.number
        %td.text-center= @ticket.expired_at

次にルーティングですが、リソースをネストさせます。

config/routes.rb

Rails.application.routes.draw do
  root 'welcome#index'
  devise_for :users, path: 'users', controllers: {
    registrations: 'users/registrations', # 登録
    confirmations: 'users/confirmations', # 確認
    sessions: 'users/sessions'            # ログイン
  }
  resources :tickets, only: %i(new create index)

  #
  # ユーザー
  #
  namespace :users do
    resources :tickets do
      resources :deliveries, only: %i(new) do
        get :confirm, to: 'deliveries#new', on: :collection
      end
    end
  end
end

詳しく知りたい方は routing(ルーティング)まとめ - さがえもん をご覧ください。

最後にトップページから、確認画面に遷移できるようにリンクを貼りましょう。

app/views/welcome/index.html.haml

.col-md-12
  %h3.text-center チケット一覧
  %table.table
    %thead
      %tr
        %th
        %th チケット名
        %th 内容
        %th.text-center チケット販売可能枚数
        %th.text-center 締切日
        %th  ## 追加
    %tbody
      - @tickets.each.with_index(1) do |ticket, index|
        %tr
          %td= index
          %td= ticket.title
          %td= ticket.body
          %td.text-center= ticket.number
          %td.text-center= ticket.expired_at
          %td.text-center  ## 追加
            = link_to '予約する', confirm_users_ticket_deliveries_path(ticket), class: 'btn btn-primary'  ## 追加

動作確認

  • トップページ f:id:sksksksksk:20180727213516p:plain

  • 確認画面 f:id:sksksksksk:20180727212343p:plain

④ 予約作成

予約作成の処理を実装します。 確認画面に「予約する」ボタンを置きます。その「予約する」ボタンをクリックすると、予約が作成されて予約完了画面に遷移します。

Deliveryコントローラーに予約を作成するcreateアクションを定義し、処理をかきます。 app/controllers/users/deliveries_controller.rb

class Users::DeliveriesController < Users::BaseController
  before_action :set_ticket, only: %i(new create)
  def new
    @delivery = Delivery.new
  end

  def create
    @delivery = current_user.deliveries.new(ticket: @ticket)
    if @delivery.save
      redirect_to # 予約完了画面のパス, notice: '予約しました'
    else
      render :new
    end
  end

  private

  def set_ticket
    @ticket = Ticket.find(params[:ticket_id])
  end
end

@ticket はnewとcreateの両方に使用しますのでコールバックでまとめます。 Deliveryを初期化しますが、current_user.deliveriesと書くことで Delivery.new(user: current_user, ticket: @ticket)よりも短く書くことができます。

create をルーティングに追加します。 config/routes.rb

・・・
   resources :deliveries, only: %i(new create) do
・・・

確認画面に「予約する」リンクを追加します。

app/views/users/deliveries/new.html.haml

.col-md-12
  %h3.text-center 予約確認画面
  %table.table
    %thead
      %tr
        ・・・・
        %th.text-center 締切日
        %th # 追加
    %tbody
      %tr
        ・・・・
        %td.text-center= @ticket.expired_at
        %td.text-center= link_to '予約する', [:users, @ticket, @delivery], method: :post, class: 'btn btn-primary' # 追加

f:id:sksksksksk:20180727220800p:plain

そのまま予約完了画面を実装しましょう。

app/views/users/deliveries/complete.html.haml

.col-md-12
  .text-center= link_to 'ホームに戻る', :root

app/controllers/users/deliveries_controller.rb

・・・
  def create
    ・・・・
    if @delivery.save
      redirect_to :users_complete, notice: '予約しました'
      ・・・
    end
  end

  def complete
  end
・・・

config/routes.rb

  #
  # ユーザー
  #
  namespace :users do
    resources :tickets do
    ・・・
    end
    get :complete, to: 'deliveries#complete' #追加
  end

f:id:sksksksksk:20180727221514p:plain

以上で予約作成の実装は完了です。 最後に動作確認をしましょう。

動作確認

  • トップページトップページの「予約する」ボタンをクリックすると、ログイン画面にリダイレクトされる。 f:id:sksksksksk:20180727222336p:plain

  • トップページからナビゲーションバーのサインアップリンクをクリックしてサインアップする。 f:id:sksksksksk:20180727222144p:plain f:id:sksksksksk:20180727222449p:plain

  • トップページから「予約する」ボタンを押すと、予約確認画面に遷移する。 f:id:sksksksksk:20180727222643p:plain

  • 「予約する」ボタンを押すと、予約が作成され予約が作成される。 f:id:sksksksksk:20180727222815p:plain

ソースコード

GitHub - sagaekeiga/ticket-reservation

質疑応答

コメントしてください。

ユーザーの作成

この記事で行うこと

チケットを予約するユーザーを作成します。

f:id:sksksksksk:20180726231701p:plain

使うもの

Ruby 2.4.2
Rails 5.1.6
devise 4.4.3

現場では?

認証機能を実装する際は今でもdeviseが主流です。
大企業や認証を頻繁にカスタマイズしたい企業などは独自の認証ライブラリを実装するケースが多いです。食べログなどは独自の認証機能を開発していると聞いたことがあります。

deviseはオーバライドしてカスタマイズすることが可能です。
一般的なサービスにおいてはほぼ間違いなくカスタマイズするのでこの記事で基本的な操作をマスターしましょう。

実装手順

① deviseのインストール

Gemfile

gem 'devise'

インストールしてください。

bundle install
② deviseの設定

deviseの関連ファイルをインストールします。

$ rails g devise:install
Running via Spring preloader in process 37183
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================


上記1~4の設定を順に行なっていきます。


1. 環境設定ファイルにデフォルトURLを設定する。
開発環境ですので、localhostを設定しましょう。

config/environments/development.rb

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

ここで本番環境も一緒に設定しておきます。

config/environments/production.rb

config.action_mailer.default_url_options = { host: ENV['WEB_DOMAIN'], protocol: 'https' }

ドメイン部分は環境(dev/stg/pro)ごとに異なるので現場では環境変数として扱います。環境変数環境変数の設定 - さがえもん を読んで設定してみましょう。

完了したらRailsサーバを再起動します。

POINT 再起動

config配下のファイルを修正したり、Gemをインストールした際は再起動をする癖をつけましょう。


2. ルートの設定
TOPページを用意します。

$ rails g controller welcome index

config/routes.rb

root 'welcome#index'

POINT 「'」(シングルクォーテーション)を使おう

なるべく「"」(ダブルクォーテーション)ではなく「'」(シングルクォーテーション)を使用しましょう。
企業の好みもありますが、「'」の方が文量が少なくなります。
さらに、「'」には、変数を含むことが('#{}'は)できないので可読性をあげることもできます。


ここまで設定するとトップページは以下のような表示になります。

f:id:sksksksksk:20180726203132p:plain


3. フラッシュメッセージの準備

ログインの成功・失敗のメッセージが表示されるようになります。
app/views/layouts/application.html.haml

!!!
%html
  %head
    %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
    %title TicketReservation
    = csrf_meta_tags
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
  %body
    %p.notice= notice
    %p.alert= alert
    = yield


4. deviseのviewファイルを作成

今後、登録・ログインページなどカスタマイズしなければならない機会があるので作成しておきましょう。今回はuserスコープで作成します。

$ rails g devise:views users
Running via Spring preloader in process 37639
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/users/shared
      create    app/views/users/shared/_links.html.erb
      invoke  form_for
      create    app/views/users/confirmations
      create    app/views/users/confirmations/new.html.erb
      create    app/views/users/passwords
      create    app/views/users/passwords/edit.html.erb
      create    app/views/users/passwords/new.html.erb
      create    app/views/users/registrations
      create    app/views/users/registrations/edit.html.erb
      create    app/views/users/registrations/new.html.erb
      create    app/views/users/sessions
      create    app/views/users/sessions/new.html.erb
      create    app/views/users/unlocks
      create    app/views/users/unlocks/new.html.erb
      invoke  erb
      create    app/views/users/mailer
      create    app/views/users/mailer/confirmation_instructions.html.erb
      create    app/views/users/mailer/email_changed.html.erb
      create    app/views/users/mailer/password_change.html.erb
      create    app/views/users/mailer/reset_password_instructions.html.erb
      create    app/views/users/mailer/unlock_instructions.html.erb

コントローラーも作成しておきます。

$ rails g devise:controllers users
Running via Spring preloader in process 37972
      create  app/controllers/users/confirmations_controller.rb
      create  app/controllers/users/passwords_controller.rb
      create  app/controllers/users/registrations_controller.rb
      create  app/controllers/users/sessions_controller.rb
      create  app/controllers/users/unlocks_controller.rb
      create  app/controllers/users/omniauth_callbacks_controller.rb
===============================================================================

Some setup you must do manually if you haven't yet:

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

===============================================================================

routes.rbは以下のように設定してください。

routes.rb

Rails.application.routes.draw do
  root 'welcome#index'
  devise_for :users, path: 'users', controllers: {
    registrations: 'users/registrations', # 登録
    confirmations: 'users/confirmations', # 確認
    sessions: 'users/sessions'            # ログイン
  }
  resources :tickets, only: %i(new create index)
end

deviseのビュー作成ではhamlの自動変換が聞かないので以下のコマンドを叩いておきましょう。

$ rails haml:replace_erbs

また、今回はUserスコープでViewを作成したのでdeviseに認識させましょう。

config/initializers/devise.rb

Devise.setup do |config|
  # The secret key used by Devise. Devise uses this key to generate
  # random tokens. Changing this key will render invalid all existing
  # confirmation, reset password and unlock tokens in the database.
  # Devise will use the `secret_key_base` as its `secret_key`
  # by default. You can change it below and use your own secret key.
  # config.secret_key = 'a7b382632d6274a5ced712f49307a5f8793d1cbd1912399a24849f1f80dc44d75510108fc81d9089f5bd82271b2ebdfa914cc7877dfd0b33c0e1bec443ce5b47'

  # ==> Controller configuration
  # Configure the parent class to the devise controllers.
  # config.parent_controller = 'DeviseController'
  config.scoped_views = true
・・・

Railsサーバを再起動させてください。


以上でdevise関連ファイルの設定は終了です。

③ ユーザーモデルの作成

deviseを使ってユーザーモデルを作成します。

$ rails g devise User

専用のマイグレーションファイルが作成されるので、データベースへ反映します。

db/migrate/20180726114118_devise_create_users.rb

# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

app/models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end


データベースへ反映

$ rails db:migrate
== 20180726114118 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0020s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0008s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0011s
== 20180726114118 DeviseCreateUsers: migrated (0.0044s) =======================
④ Viewの編集

登録・ログイン画面に遷移できるようにリンクをつけてあげます。

app/views/layouts/application.html.haml

  %body
    %header
      %nav
        - if user_signed_in?
          %strong= link_to 'ホーム', :root
          = link_to 'プロフィール変更', :edit_user_registration
          = link_to 'ログアウト', :destroy_user_session, method: :delete
        - else
          = link_to 'サインアップ', :new_user_registration
          = link_to 'ログイン', :new_user_session
    %p.notice= notice
    %p.alert= alert
    = yield

動作確認

① トップページ

f:id:sksksksksk:20180726211357p:plain

② サインアップ(登録)ページ

f:id:sksksksksk:20180726211500p:plain

③ サインアップ後のトップページ

f:id:sksksksksk:20180726211626p:plain

質疑応答

コメントしてください。

ProgateやRailsチュートリアル、プログラミングスクールを通い終えたが現場のコードはかけない、

一体どうやって書くの?と思っているエンジニアのみなさんのためのチュートリアルを公開しています。

チュートリアル