rails 独学して軽くにちゃんまとめつくる

読者です 読者をやめる 読者になる 読者になる

rails独学して軽く2ちゃんまとめビルダーをつくる。

rails tutorial読破→2chまとめビルダー作成→アメリカでインターンシップ→恋活SNSを作成・・・・・→音で感触をつくり感触をあつめたライブラリをつくる

アカウントの有効化

メールの体裁,メールの送信

$ rails generate mailer UserMailer account_activation password_reset 

 これをすると以下のファイルなどが作られる.

 

メーラーのフロントエンド

HTMLのテンプレート

app/views/user_mailer/account_activation.html.erb

テキストのテンプレート

app/views/user_mailer/account_activation.text.erb

 

メールのバックエンド

全体に適応されるメーラー

app/mailers/application_mailer.rb

個別に設定できるメーラー
app/mailers/user_mailer.rb

 

これらフロントエンドとバックエンドに大別される.

ここではバックエンドから修正していく.とはいえ送り先を指定するだけ.メソッドを呼び出すときにユーザーを引数にして,そのユーザーからemail カラムを引っ張りだしてくる.ただそれだけ

 

app/mailers/user_mailer.rb

def account_activation(user)
    @user = user
    mail to: user.email, subject: "Account Activation"
end

 

フロントエンドも単純.ただし,メールの内容にアクティベーションするためのリンクを仕込んでおく必要がある.リンクは edit アクションを起動させるようにしてある.メールの画面もウェブサイトの一画面とかんがえたらわかりやすい.

 

Hi <%= @user.name %>,
Welcome to the Sample App! Click on the link below to activate your account:

<%= edit_account_activation_url(@user.activation_token, email: @user.email) %>

 

<h1>Sample App</h1>

<p>Hi <%= @user.name %>,</p>

<p>
Welcome to the Sample App! Click on the link below to activate your account:
</p>
<%= link_to "Activate", edit_account_activation_url(@user.activation_token,
email: @user.email) %>

 

メーラーじたいの操作はこれで終わり.次にいままで作ってきたUserリソースにメーラーを組み込んでいく作業をする.

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

  1. ユーザーの初期状態は「有効化されていない」(unactivated) にしておく。
  2. ユーザー登録が行われたときに、有効化トークンと、それに対応する有効化ダイジェストを生成する。
  3. 有効化ダイジェストはデータベースに保存しておき、有効化トークンはメールアドレスと一緒に、ユーザーに送信する有効化用メールのリンクに仕込んでおく2
  4. ユーザーがメールのリンクをクリックしたら、アプリケーションはメールアドレスをキーにしてユーザーを探し、データベース内に保存しておいた有効化ダイジェストと比較することでトークンを認証する。
  5. ユーザーを認証できたら、ユーザーのステータスを「有効化されていない」から「有効化済み」(activated) に変更する。

 

 

コントローラーの作成

$ rails generate controller AccountActivations

ルーティング

  resources :account_activations, only: [:edit]

 

Usersモデルにカラムの追加

認証系だから,ダイジェストカラム activation_digest を追加する.そのほかにも有効化しかたどうかを知る activated と,有効化した時間を記録する activated_at

$ rails generate migration add_activation_to_users  activation_digest:string activated:boolean activated_at:datetime

 

マイグレーションファイルに activated が初期状態では false であることを記入

class AddActivationToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :activation_digest, :string
    add_column :users, :activated, :boolean, default: false
    add_column :users, :activated_at, :datetime
  end
end

 

$ rails db:migrate

 

 

ユーザーが新しい登録を完了するためには必ずアカウントの有効化が必要になるのですから、有効化トークンや有効化ダイジェストはユーザーオブジェクトが作成される前に作成しておく必要がある.activation_token は仮のカラムだから attr_accsessor で作成しておき, token_digest はカラムとして存在するのでそのままでおっけー.セッターだからself はつけておく.

 

attr_accessor :remember_token, :activation_token before_create :create_activation_digest



private
def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(activation_token) end

 

開発環境でつかうユーザーの有効化をしておく.

db/seed.rb

User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar",
             admin:     true,
             activated: true,
             activated_at: Time.zone.now)

 

 

 

 

ユーザーが新規登録をしたときにメーラーが起動するようにしたいから,users_controllerの create アクションを変更する.先ほどまでは新規登録したら即ログインしてたが,それを取っ払ってメールを送ることにする.

 

中に書いてあることも至極当然.まずはじめはメールを送る.updateやcreate のあとはメッセージを送るから flash をかく.ビューのないアクションの最後にはredirect_to か render をつける.これらはすべて定石だから覚えておくべき.

 

 

def create
    @user = User.new(user_params)
    if @user.save
      UserMailer.account_activation(@user).deliver_now
      flash[:info] = "有効かメールをおくりました."
      redirect_to root_url
    else
      render 'new'
    end
  end 

 

 

authenticated? メソッドの変更

認証にはパターンが存在する

 

f:id:mooooooooooriiiiii:20161218171545p:plain

 

上の画像のように「検索キー」「トークン」「ダイジェスト」「ダイジェストとトークンが一致するかの認証メソッド」の4つを使って認証を行っている.クッキーを使ったログイン省略機能をつくるときに作成した authenticated? メソッドを改良する.

 

models/user.rb

# トークンがダイジェストと一致したらtrueを返す
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

 

 

 

 

アカウントの有効かをする.

 

app/controllers/account_activations_controller.rb

def edit
    user = User.find_by(email: params[:email])
    if user && !user.authenticated? && user.authenticated(:activation, params[:id])
      user.update_attribute(:activated,      true)
      user.update_attribute(:activated_at, Time.zone.now)
      log_in user
      flash[:success] = "アカウントが有効かされました."
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
end

 

 

 

あとの微調整

有効化してないユーザーのログインを禁止する.

app/controllers/sessions_controller.rb

def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      if user.activated?
        log_in user
        params[:session][:remember_me] == '1' ? remember(user) : forget(user)
        redirect_back_or user
      else
        message  = "Account not activated. "
        message += "Check your email for the activation link."
        flash[:warning] = message
        redirect_to root_url
      end
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

 

 

ここで,authenticated? メソッドを変えてしまったので,すでに定義してしまったのを変えておく.

 

app/helpers/sessions_helper.rb

if user && user.authenticated?(:remember, cookies[:remember_token])

 

 

 

 

 

メーラーのバックエンドを整える.ユーザーを引数でうけとり,アドレスを知る

フロントエンドを整える

2新規登録したときにメールを送信する

3受信したメールが正しいか authentiated? メソッドで確かめる.