RailsのdeviseとStripe(とBootstrap)の組み合わせで、ただただユーザー登録したユーザーに定期更新購読させるだけのappを作りました①


# 前書き

初心者向けに自分なりの言葉で柔らかく書いたつもりです。非エンジニアですが、メモ目的とアウトプットの恩恵のために記事にしました。間違っているところなどありましたら、コメントをください。
あとコードにコメントが多く視認性が悪いかもしれません。そこは申し訳なく…

**※stripe実装やBootstrap実装は長くなってしまっているので②③の記事で分けて記述しています。**
[RailsのdeviseとStripe(とBootstrap)の組み合わせで、ただただユーザー登録したユーザーに定期定額課金させるだけのappの実装方法②](https://qiita.com/Rafflesia/items/5ce936656c6f99c144ef)
[RailsのdeviseとStripe(とBootstrap)の組み合わせで、ただただユーザー登録したユーザーに定期定額課金させるだけのappの実装方法③](https://qiita.com/Rafflesia/items/95ecc4f46200861bd0ea)





## 参考記事

- ### Rails周り
    - [Railsのモデルの作成、検索、更新、削除のよく使うメソッドのまとめ](http://ruby-rails.hatenadiary.com/entry/20140724/1406142120#ar-update)
    - [Railsのモデル検索あれこれ](https://qiita.com/tono0123/items/576a4a4659b51860f304)
    - [rails generate migrationコマンドまとめ](https://qiita.com/zaru/items/cde2c46b6126867a1a64)
    - [[Ruby入門] 14. 日付と時刻を扱う（全パターン網羅）](https://qiita.com/prgseek/items/c0fc2ffc8e1736348486)
    - [Railsバリデーションまとめ](https://qiita.com/shunhikita/items/772b81a1cc066e67930e)
    - [【Rails入門】saveがすべて成功したことを保証する(transaction)](https://www.sejuku.net/blog/27240)
    - [これは便利！すぐに使える、CSSをSASS/SCSSに簡単に変換できるツール](https://y-com.info/contents/?p=4630)
    - [railsのrenderとredirect_toの違い](https://qiita.com/1ulce/items/282cccba1e44158489c8)
    - [Ruby on Railsのオブジェクト存在チェック4種](https://qiita.com/hnkyi/items/f6c615909163a30b9814)
    - [RailsでjQueryを読み込まずにmethod: :deleteのリンクを実現する（Routing Error No route matches [GET] ... の対処法）](https://qiita.com/y-temp4/items/2d50feb3ff0d65acdf67)



- ### devise周り
    - [Ruby on Rails - deviseを使ってユーザの認証機能をカンタン実装](https://miningoo.com/1343/)
    - [Deviseの設定手順をまとめてみた。 その1　導入編](https://qiita.com/itboze/items/ea0d9236d89fa24a7a1c)
    - [[*Rails*] deviseの使い方（rails5版）](https://qiita.com/cigalecigales/items/f4274088f20832252374)
    - [railsの日本語化 deviseの日本語化](https://qiita.com/shizuma/items/a52fd0ef5b60d61fa330)



- ### stripe周り
    - [Rails Stripe サブスクリプション決済実装 初期設定をしてAPIを使える状態にする](https://qiita.com/ayies128/items/8c5ec353a842d5d30e77#_reference-21017f753033baadbc8e)
    - [日本正式リリースしたStripeを使ってサブスクリプション型決済システムを実装する](https://qiita.com/tady/items/7617e62b2a5402ebd0fb)
    - [stripeドキュメント](https://stripe.com/docs)
    - [stripeドキュメントBillingクイックスタート](https://stripe.com/docs/billing/quickstart)
    - [Stripe Billing 101](https://qiita.com/y_toku/items/235b5e7ee00792edcbbf)
    - [Stripe で webhook エンドポイントを実装する際のポイント](https://qiita.com/ororog/items/ca0b4657ea47c4f7b406)



- ### bootstrap周り
    - [Rails5にBootstrapを導入する](https://qiita.com/tqkqt0/items/d9a3f3416c242ba48ba0)
    - [RailsでBootstrapを使うには？実際にボタンを作って学べる！](https://udemy.benesse.co.jp/development/rails-bootstrap.html)
    - [Rails で Bootstrap を使う gem「bootstrap-sass」を導入する](http://neos21.hatenablog.com/entry/2017/03/17/000347)










# Rails実装開始



## 環境
- ruby 2.3.1p112
- Rails 5.2.0
- devise (4.4.3)
- stripe (3.17.2)




## プロジェクト作成

好きな場所にプロジェクトを作成する。

```
$ rails new stripe1.0.0
$ cd stripe1.0.0
```




# devise実装




##gem編集

devise機能を実装するためにgemからインストールする準備として、いつも通りGemfileに'devise'の記述を追加。

```:Gemfile
source 'https://rubygems.org'

gem '~~~~~~'
gem '~~~~~~'

# gemと並んでいる行の好きな行に下記の行を追加
gem 'devise'
gem '~~~~~~'

```

gemをRailsにインストール。

```
$ bundle install
```



## プロジェクト内にdevise機能を実装

```
$ rails g devise:install
```




## デフォルトURLの指定

```Ruby:config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```




## ルート(トップページ)となるページの作成

トップページにするコントローラーとアクションを作成する。
まずはコントローラーから作成。
コントローラー名(Home部分)は何でも良い。

```
$ rails g controller Home
```



## アクションの追加

```Ruby:app/controllers/home_controller.rb
class HomeController < ApplicationController

    def index
    end

end
```
前述のコントローラー作成時に$ rails g controller Home indexとしてもアクション付きのコントローラーができるのでそれでも良い。




## ルート(トップページ)に設定

:config/routes.rbにトップにしたコントローラー#アクションを記述。

```Ruby:config/routes.rb
Rails.application.routes.draw do
  # トップにするコントローラー#アクションを記述
  root 'home#index'
end
```



## application.html.erbにメッセージを追加

viewの共通部分を描写するapplication.html.erbに認証メッセージを描写できるようにする。

```erb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>

    <!-- 好きなタイトルにする -->
    <title>Stripe1.0.0</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

  </head>
 
  <body>

    <!-- メッセージが入るところ -->
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
 
    <!-- 他のViewファイル(~~~.html.erb)が入るところ -->
    <%= yield %>

  </body>
</html>
```




##  deviseのviewを作成

サインアップ画面や、ログイン画面、認証情報編集画面、パスワード変更画面、メールアドレス変更画面などのdeviseのViewを生成。

```
$ rails g devise:views
```




##  deviseのUserを作成

通常のUserモデルにdevise認証で必要なカラムを追加したUserモデルを生成するコマンドを実行。

```
$ rails g devise User
```

Userモデル生成時に生成されたマイグレーションファイルを以下のようにコメントを外して変更する。

変更前

```Ruby:db/migrate/0123456789_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  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
```

変更後

```Ruby:db/migrate/0123456789_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  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
```

変更前

```Ruby: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
```

変更後

```Ruby: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,# ←,を忘れないように
         # ここから追加
         :confirmable, :lockable, :timeoutable
end
```

マイグレーションを実行してdeviseに適用したUserテーブルを作成。

```
$ rails db:migrate
```



## application.html.erbにheaderの追加

viewの共通部分を描写するapplication.html.erbにhead部分を追加して、どの画面でもサインアップやログイン、ログアウトなどができるようにリンクを追加して改造する。

```erb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>

    <title>Stripe1.0.0</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
 
  <body>

    <!-- 追加する箇所*************************** -->
    <header>
      <nav>
        <ul>
        <% if user_signed_in? %>
          <li>
            <%= link_to ‘認証情報の変更’, edit_user_registration_path %>
          </li>
          <li>
            <%= link_to ‘ログアウト’, destroy_user_session_path, method: :delete %>
          </li>
        <% else %>
          <li>
            <%= link_to ‘サインアップ’, new_user_registration_path %>
          </li>
          <li>
            <%= link_to ‘ログイン’, new_user_session_path %>
          </li>
        <% end %>
        </ul>
      </nav>
    </header>
    <!-- ************************************** -->


    <!-- メッセージが入るところ -->
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>

    <!-- 他のViewファイル(~~~.html.erb)が入るところ -->
    <%= yield %>

  </body>
</html>
```






## メールの設定

config/initializers/devise.rbに、送信に使用するメールアドレスを設定する。

```Ruby:config/initializers/devise.rb
 
  Devise.setup do |config|
  #
  #
  config.mailer_sender = 'メールアドレス'# 送信元の表示設定
  #
  #
end
```

config/environments/development.rbにメールのsftp情報を編集

```Ruby:config/environments/development.rb
 
  # mail setting
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => "smtpサーバー名",
    :port => '587',
    :user_name => "アカウント名",
    :password => "パスワード",
    :authentication => :login,
    :enable_starttls_auto => true
  }
end
```

サインアップ時に登録メールアドレスにメールが送信され、メール内にあるリンクを押すことによって認証を完了させる、よくあるあれ。
もしもメールが届かなかった場合でも、サインアップ完了時にターミナルに表示される文字列の中に、アクセスするためのリンクのアドレスが表示されているので、これをコピーしてブラウザで検索させることでも完了させることができる。

届いたメールの本文等を編集したい場合はapp/views/devise/confirmation_instructions.html.erbに項目があるので編集する。





## ログイン時に間違えて良い回数の設定

```Ruby:config/initializers/devise.rb
  config.unlock_strategy = :email# emailをアンロックにする
  config.maximum_attempts = 5# 失敗の回数
```





## タイムアウトにする時間の設定

```Ruby:config/initializers/devise.rb
  config.timeout_in = 30.minutes
```




## アクセス制限

viewの共通部分を描写するapplication_controller.rbにアクセス制限の記述をする。

```Ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!# アクセス制限
end
```






# stripe実装

記事の初めにも記述しましたが、stripe実装は今回のdevise認証で長くなってしまったので②の記事で紹介しています。
こちらをご覧下さい。
[]()