【125日目】【1日20分のRailsチュートリアル】【第10章】アカウント有効化メールのプレビューを確認する
今日は「10.1.2 AccountActivationsメイラーメソッド」のUserメイラーのプレビューファイルを更新するところから。
10.1.2 AccountActivationsメイラーメソッド
developmentサーバーを再起動してリスト10.14の設定を読み込んだら、次は10.1.2で自動生成したUserメイラーのプレビューファイルの更新が必要です。
リスト10.11で定義したaccount_activationの引数には有効な (=実在する) ユーザーオブジェクトを渡す必要があるため、リスト10.15はこのままでは動きません。
あー、そういえばメソッドに引数追加したわ。
ユーザーオブジェクトはデータベースの最初のユーザーになるようにして渡す。
リスト10.16ではuser.activation_tokenにも値を代入している点にご注目ください。リスト10.12やリスト10.13のアカウント有効化テンプレートではアカウント有効化トークンが必要なので、代入は省略できません。
アカウント有効化メールでトークンを必要とするようにしたから、ってことだよね。。。
test/mailers/previews/user_mailer_preview.rb
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/account_activation def account_activation user = User.first user.activation_token = User.new_token UserMailer.account_activation(user) end
ここまでできたらアカウント有効化メールのプレビューが確認できるらしい。
サーバーを起動して
$ rails server -b $IP -p $PORT
http://<ローカルアドレス>/rails/mailers/user_mailer/account_activation
にアクセス。(URLってどっから分かるの、、と思ってたらさっき編集したファイルにコメントで書かれてた)
HTML版もテキスト版も見れました。
今日の学習時間は【20分】。
次は「10.1.2 AccountActivationsメイラーメソッド」のメールプレビューのテストを作成するところから。
【124日目】【1日20分のRailsチュートリアル】【第10章】アカウント有効化メールのビューを作成する
今日は「10.1.2 AccountActivationsメイラーメソッド」のメールにアカウント有効化リンクを追加するところから。
10.1.2 AccountActivationsメイラーメソッド
ここでは挨拶文にユーザー名を含め、カスタムの有効化リンクを追加します。
この後、Railsサーバーでユーザーをメールアドレスで検索して有効化トークンを認証できるようにしたいので、リンクにはメールアドレスとトークンを両方含めておく必要があります。
account_activations/q5lt38hQDc_959PVoo6b7A/edit?email=foo%40example.com
こんな感じでURLにトークンとメールアドレスを含めておくようにする。
ここまでできれば、リスト10.11で定義した@userインスタンス変数、editへの名前付きルート、ERBを組み合わせて、必要なリンクを作成できます (リスト10.12とリスト10.13)。
○テキストビュー
app/views/user_mailer/account_activation.text.erb
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) %>
○HTMLビュー
app/views/user_mailer/account_activation.html.erb
<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) %>
今更だけどテキストビューとHTMLビューがあるのは送り先によってテキストメール送るかHTMLメールで送るか違うからなのかな。
リスト10.12やリスト10.13で定義したテンプレートの実際の表示を簡単に確認するために、メールプレビューという裏技を使ってみましょう。
へー、そんな機能が。動作確認のために実際にメール送らないといけないのかと思ってた。
これを利用するには、アプリケーションのdevelopment環境の設定に手を加える必要があります (リスト10.14)。
元々あったconfig.action_mailer.raise_delivery_errors = false
は削除した。
config/environments/development.rb
: # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :test host = 'rails-tutorial-c9-mhartl.c9.io' config.action_mailer.default_url_options = { host: host } :
今日の学習時間は【25分】。
次は「10.1.2 AccountActivationsメイラーメソッド」のUserメイラーのプレビューファイルの更新をするところから。
ここまで来ると1項が長いね…。
【123日目】【1日20分のRailsチュートリアル】【第10章】UserMailerを生成してテンプレートをカスタマイズする
今日は「10.1.2 AccountActivationsメイラーメソッド」から。
10.1.2 AccountActivationsメイラーメソッド
メイラーの構成はコントローラのアクションとよく似ており、メールのテンプレートをビューと同じ要領で定義できます。
この節ではメイラーとビューを定義して、有効化トークンとメールアドレス (=有効にするアカウントのアドレス) を含むリンクをその中で使用します。
「メイラー」がそもそもよく分からないんだけど、アプリケーションでメール送るためのクラスみたいな感じかな…??
メイラーは、モデルやコントローラと同様にrails generateで生成できます。
下記コマンドで「UserMailer」を生成。
$ rails generate mailer UserMailer account_activation password_reset
生成したメイラーごとに、ビューテンプレートが2つずつ生成されます。1つはテキストメール用のテンプレート、1つはHTMLメール用テンプレートです。
下記テンプレートが生成されたことを確認。
app/views/user_mailer/account_activation.text.erb
UserMailer#account_activation <%= @greeting %>, find me in app/views/user_mailer/account_activation.text.erb
app/views/user_mailer/account_activation.html.erb
<h1>UserMailer#account_activation</h1> <p> <%= @greeting %>, find me in app/views/user_mailer/account_activation.html.erb </p>
リスト10.8には、デフォルトのfromアドレス (アプリケーション全体で共通) があります。
リスト10.9の各メソッドには宛先メールアドレスもあります。リスト10.8ではメールのフォーマットに対応するメイラーレイアウトも使用されています。
デフォルトのfromアドレスは"from@example.com"になってる。
app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base default from: "from@example.com" layout 'mailer' end
宛先メールアドレスは"to@example.org"になってるけどここは相手によって変えるとこかな…?
app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # # en.user_mailer.account_activation.subject # def account_activation @greeting = "Hi" mail to: "to@example.org" end # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # # en.user_mailer.password_reset.subject # def password_reset @greeting = "Hi" mail to: "to@example.org" end end
最初に、生成されたテンプレートをカスタマイズして、実際に有効化メールで使えるようにします (リスト10.10)。
デフォルトのfromアドレスを"noreply@example.com"に変更。
app/mailers/application_mailer.rb
default from: "noreply@example.com"
次に、ユーザーを含むインスタンス変数を作成してビューで使えるようにし、user.emailにメール送信します (リスト10.11)。
account_activationメソッドを引数ありに変更して、user.emailにメール送信するように変更。ついでにメールの件名も設定。
app/mailers/user_mailer.rb
def account_activation(user) @user = user mail to: user.email, subject: "Account activation" end
途中だけど今日はここまで。
今日の学習時間は【25分】。
次は「10.1.2 AccountActivationsメイラーメソッド」のメールにアカウント有効化リンクを追加するところから。
【122日目】【1日20分のRailsチュートリアル】【第10章】アカウントの有効化トークンやダイジェストを作成する処理を追加する
今日は「10.1.1 AccountActivationsリソース」のアカウントの有効化について考えるところから。
10.1.1 AccountActivationsリソース
ユーザーが新しい登録を完了するためには必ずアカウントの有効化が必要になるのですから、有効化トークンや有効化ダイジェストはユーザーオブジェクトが作成される前に作成しておく必要があります。
before_create
コールバックを使うとユーザーオブジェクト作成前に有効化トークンや有効化ダイジェストを作成できるそう。
Userモデルに有効化トークンとダイジェストを作成する処理を追加する。
ついでにメールアドレスを小文字に変換する処理もちょっと書き換える。
app/models/user.rb
class User < ActiveRecord::Base attr_accessor :remember_token, :activation_token before_save :downcase_email before_create :create_activation_digest : private # メールアドレスをすべて小文字にする def downcase_email self.email = email.downcase end # 有効化トークンとダイジェストを作成および代入する def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(activation_token) end end
先に進む前に、サンプルデータとフィクスチャも更新し、テスト時のサンプルとユーザーを事前に有効化しておきましょう (リスト10.4とリスト10.5)。
サンプルデータ更新。
db/seeds.rb
User.create!(name: "Example User", : activated: true, activated_at: Time.zone.now) 99.times do |n| : activated: true, activated_at: Time.zone.now) end
フィクスチャの各ユーザーに下記コードを追加。
test/fixtures/users.yml
: activated: true activated_at: <%= Time.zone.now %> :
いつものようにデータベースを初期化して、サンプルデータを再度生成し直し、リスト10.4の変更を反映します。
下記を実行してサンプルデータを再度生成し直しました。
$ bundle exec rake db:migrate:reset $ bundle exec rake db:seed
これでようやく準備的なものは終わりなのかな…??
今日の学習時間は【19分】。
次は「10.1.2 AccountActivationsメイラーメソッド」から。
【121日目】【1日20分のRailsチュートリアル】【第10章】アカウント有効化のためにUserモデルに属性を追加する
今日は「10.1.1 AccountActivationsリソース」のresources行を追加するところから。
10.1.1 AccountActivationsリソース
有効化メールでは以下の形式のURLを使用します。
edit_account_activation_url(activation_token, ...)
これは、editアクションへの名前付きルートが必要になるということです。そのためのresources行を追加します (リスト10.1)。
ほぅ…そうなのか。。。
よく分かってないけど下記を追加。
config/routes.rb
resources :account_activations, only: [:edit]
続いて、一意の有効化トークンがユーザー有効化に必要です。
パスワードのときと同じように有効化トークンを使えばいいってことかな。。。
- activation_digest
- activated
- activated_at
の3つの属性を追加。
$ rails generate migration add_activation_to_users activation_digest:string activated:boolean activated_at:datetime invoke active_record create db/migrate/20170313024742_add_activation_to_users.rb
admin 属性 (リスト9.50) の時と同様に、activated属性のデフォルトの論理値をfalseにします (リスト10.2)。
さっき生成したファイルを下記のように修正してマイグレーション実行。
db/migrate/[timestamp]_add_activation_to_users.rb
add_column :users, :activated, :boolean, default: false
$ bundle exec rake db:migrate == 20170313024742 AddActivationToUsers: migrating ============================= -- add_column(:users, :activation_digest, :string) -> 0.0006s -- add_column(:users, :activated, :boolean, {:default=>false}) -> 0.0035s -- add_column(:users, :activated_at, :datetime) -> 0.0004s == 20170313024742 AddActivationToUsers: migrated (0.0049s) ====================
まだ中途半端だけど今日はここまで。
今日の学習時間は【20分】。
次は「10.1.1 AccountActivationsリソース」のアカウントの有効化について考えるとこから。
【120日目】【1日20分のRailsチュートリアル】【第10章】AccountActivationsリソースを生成する
今日は「第10章 アカウント有効化とパスワード再設定」から。
今日から10章!
第10章 アカウント有効化とパスワード再設定
アカウントの有効化 (アクティベーション: 新規ユーザーのメールアドレスが有効であることを確認する機能) と、パスワードの再設定 (パスワードを忘れてしまったユーザー向けの機能) を実装することにします。
「アカウントの有効化」ってなんだろう、と思ってた。なるほどね。
10.1 アカウントの有効化
おおよその流れは、有効化トークンやダイジェストをユーザーと関連付け、ユーザーにメールを送信し、そのメールにはトークンを含むリンクを記載しておき、ユーザーがそのリンクをクリックすると有効化できるようになる、というものです。
ほぅほぅ。新規登録するときによくある流れだけどその裏側が理解できるってことか。
それではいつものように、Gitで新機能用のトピックブランチを作成しましょう。
10.3で説明したとおり、アカウントの有効化とパスワードの再設定では、メールの設定部分に共通するところがありますので、その部分を両機能に適用してからGitのmasterにマージします。
10章用にブランチ作成する。
$ git checkout master $ git checkout -b account-activation-password-reset
10.1.1 AccountActivationsリソース
この作業に必要なデータ (有効化トークンや有効化ステータスなど) をUserモデルに追加することにします。
ひとまずAccountActivationsコントローラを下記コマンドで生成。
$ rails generate controller AccountActivations --no-test-framework : create app/controllers/account_activations_controller.rb invoke erb create app/views/account_activations invoke helper create app/helpers/account_activations_helper.rb invoke assets invoke coffee create app/assets/javascripts/account_activations.coffee invoke scss create app/assets/stylesheets/account_activations.scss
上のコマンドでは、テストを生成しないというオプションを指定していることにご注目ください。
著者はコントローラのテストよりも統合テスト (10.1.4) の方が望ましいと考えているので、コントローラのテストを生成しないようにしているのです。
ほぅ…。何が違うのか分かってないけど今はいいか。。。
中途半端だけど今日はここまで。
今日の学習時間は【21分】。
次は「10.1.1 AccountActivationsリソース」のresources行を追加するところから。
【119日目】【1日20分のRailsチュートリアル】【第9章】演習の4.
今日は「9.6 演習」の4.から。
9.6 演習
4.リスト9.60のパーシャルを使用して、new.html.erbビューとedit.html.erbビューをリファクタリングし、コードの重複を取り除いてください。
このとき、リスト9.61のようにフォーム変数fを明示的にローカル変数として渡す必要があることに注意してください。
また、provide関数を使うと、パーシャル化したnewフォームやeditフォームの重複をさらに取り除くことも可能です。
まずリスト9.60のパーシャルを作成する。
ファイルを作成して
$ touch app/views/users/_form.html.erb
下記のように更新。
app/views/users/_form.html.erb
<%= form_for(@user) do |f| %> <%= render 'shared/error_messages', object: @user %> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation, class: 'form-control' %> <%= f.submit yield(:button_text), class: "btn btn-primary" %> <% end %>
new.html.erbビューをリスト9.61のようにリファクタリング。
<% provide(:button_text, 'Create my account') %>
を2行目に追加して、<%= render 'form' %>
でパーシャル使う。
app/views/users/new.html.erb
<% provide(:title, 'Sign up') %> <% provide(:button_text, 'Create my account') %> <h1>Sign up</h1> <div class="row"> <div class="col-md-6 col-md-offset-3"> <%= render 'form' %> </div> </div>
edit.html.erbビューも同じようにリファクタリング。
app/views/users/edit.html.erb
<% provide(:title, "Edit user") %> <% provide(:button_text, "Save changes") %> <h1>Update your profile</h1> <div class="row"> <div class="col-md-6 col-md-offset-3"> <%= render "form" %> <div class="gravatar_edit"> <%= gravatar_for @user %> <a href="http://gravatar.com/emails" target="_blank">change</a> </div> </div> </div>
サーバー起動してユーザー登録画面とユーザー情報編集画面表示させてみたけど特に問題なさそう。
リファクタリングできたかな。
$ rails server -b $IP -p $PORT
画面によってボタンの文字列もちゃんと変わってる。
今日の学習時間は【25分】。
次は「第10章 アカウントの有効化とパスワードのリセット」から。
やっと10章。まだまだ先は長いね…。