【Ruby on Rails】sorceryを使用したログインで、ユーザーネーム・emailのどちらでもログインできるようにする
Deviseでの方法はいくらでもあるのですけど、sorceryについてはなかなか見つからなかったもので。
Rails version 4.2.5
Ruby version 2.3.0-p0 (x86_64-linux)
sorcery (0.9.1)
前提:公式のこちらのチュートリアルに沿って、emailでのログインは可能になっていること。つまり途中から導入する場合ということになります。
マイグレーションファイルの編集
db/migrate/****_sorcery_core.rbにて
class SorceryCore < ActiveRecord::Migration def change create_table :users do |t| t.string :email, :null => false t.string :username, :null => false # これを追加 t.string :crypted_password t.string :salt t.timestamps end add_index :users, :email, unique: true add_index :users, :username, unique: true # これを追加 end end
emailの他に、今回はusername
というカラムを作ります。
そして、rake db:migrate:reset
を行いました。もうすでにDBにユーザーを作っていたのですが、それにはusername
を設定していなかったので、リセットを行うことにしました。
設定ファイルの編集
config/initializers/sorcery.rb
にて
# --- user config --- config.user_config do |user| # -- core -- # specify username attributes, for example: [:username, :email]. # Default: `[:email]` # user.username_attribute_names = [:username, :email]
user.username_attribute_names
に:email
だけでなく、:username
も追加します。
Strong Parametersへの追加
app/controllers/users_controller.rb
def user_params params.require(:user).permit(:username, :email, :password, :password_confirmation) end
User modelにバリデーション追加
app/models/user.rb
validates :email, :username, presence: true . . validates :username, uniqueness: true
:username
にpresence: true
とuniqueness: true
のバリデーションをかけます。
ログインフォームの編集
ユーザーネーム用・email用のフォームを一つにまとめたい。
どうすればいいのかなあ、と思って試行錯誤したのですが、以下の方法にしました。
app/views/user_sessions/_form.html.erb
ログイン画面にてemail用のフィールドの代わりに、下記のコードに置き換えます。
<div class="field"> <%= label_tag :login %><br /> <%= text_field_tag :login, nil, placeholder: 'username or email' %> </div>
params[:login]というのをコントローラーに渡すようにしておきます。ここにユーザーネーム、emailのどちらかが入ることになります。
セッション用コントローラーの編集
app/controllers/user_sessions_contoller.rb
def create # params[:login] is username or email if @user = login(params[:login], params[:password], params[:remember_me]) redirect_back_or_to(:users, notice: 'Login successfully') else flash.now[:alert] = 'Login failed' render :new end end
デフォルトではlogin
メソッドの第1引数にparams[:email]
を渡していましたが、ここではparams[:login]
を渡します。
Processing by UserSessionsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"****", "login"=>"user1", "password"=>"[FILTERED]", "commit"=>"Login", "remember_me"=>"on"} User Load (1.9ms) SELECT "users".* FROM "users" WHERE ("users"."username" = 'user1' OR "users"."email" = 'user1') ORDER BY "users"."id" ASC LIMIT 1
フィールドにuser1
というユーザーネームでログインしたところをconsoleで見てみます。
usersテーブルのusername
かemail
のどちらかにuser1
があるかどうか、検索してくれていますね。
Processing by UserSessionsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"****", "login"=>"test@example.com", "password"=>"[FILTERED]", "commit"=>"Login", "remember_me"=>"on"} User Load (0.5ms) SELECT "users".* FROM "users" WHERE ("users"."username" = 'test@example.com' OR "users"."email" = 'test@example.com') ORDER BY "users"."id" ASC LIMIT 1
今度はtest@example.com
でログインしたところ。こちらでもOR
検索してくれています。
その他
- ユーザーネームも必須にしたので、ユーザー登録画面(app/views/users/_form.html.erb)に、
username
用のフォームを追加する。 - ユーザーの一覧・詳細画面にもユーザーネームを表示する
ということをしました。
参考
こちらの記事では、emailからユーザーネームでのログインに置き換える、ということをしています。
(追記)
うーん、記事を投稿してすぐに気がついたのですけど、もしユーザーネームのほうにふざけてuser@example.com
などと、emailと同じ形式で登録してしまうと、他のユーザーのemail
とかぶってしまうことが無きにしもあらず、のような気がしました。
ユーザーネームには@
, .
(+
も?)などは使えないようにバリデーションをかける必要があるかもです。
(さらに追記)
こう・・・かな?
app/models/user.rb
validates :username, format: { with: /\A\w+\z/ }
単語、数字、アンダースコアだけに制限すると。
【Ruby on Rails】Cloud9 + Heroku + SendGridで本番環境からメールを飛ばす
現在Udemyでこのような講座をやっていまして
開発環境はCloud9、デプロイ先はHerokuでのお話です。
Herokuでの準備
Heroku>Dashboard>左ペインManage Account>Billing
でクレカ情報登録をしておきます。
Cloud9のコンソールにてheroku addons:create sendgrid:starter
Herokuのダッシュボードよりアプリのページを見ると
Sendgridが連携されているのがわかります。ここをクリックすると、SendGridのページへ飛びます。
「なんか問題あったらメール送るから!メルアド教えてくれ!」みたいなポップアップがでますが、もうすでにapp********@heroku.com
というメルアドがフォームには入っています。とにかくボタンを押してみましたが、だめだw
もう一回Gmailで登録し直しました。
SendGridでの設定
左のSettings>Credentials>New Credentials
からusername
, password
の設定。mail
にチェックを入れます。
Heroku用の環境変数設定
Cloud9のコンソールにて、
heroku config:set SENDGRID_USERNAME=yourusername
heroku config:set SENDGRID_PASSWORD=youruserpassword
先ほどSendGridで登録したユーザーネームとパスワードを設定します。
開発環境の環境変数設定
チュートリアルでは.zshrc
に記述しているようですが、dotenv(dotenv-rails)
を使います。
公式を見るとGemfileのトップに記述するようですが、まあruby
のすぐ後にしました。
source 'https://rubygems.org' ruby "2.2.4" gem 'dotenv-rails', :groups => [:development, :test]
bundle install
したあとは忘れずに.gitignore
に.env
を追加。そしてプロジェクトのルートにて.env
ファイルを作成し、
SENDGRID_USERNAME=yourusername SENDGRID_PASSWORD=yourpassword
と記述しておきます。
ActionMailer設定
config/environment.rb
ActionMailer::Base.smtp_settings = { :address => 'smtp.sendgrid.net', :port => '587', :authentication => :plain, :user_name => ENV['SENDGRID_USERNAME'], :password => ENV['SENDGRID_PASSWORD'], :domain => 'heroku.com', :enable_starttls_auto => true }
ここの答えを見るとCloud9はport587
をブロックするようだから、2525とか別のポートにしたほうがいいぜ!みたいなことが書いてありましたが、その通りにすると今度は本番環境にてうまくいかなくなりましたので、おとなしく587
を指定しました。
config/environments/development.rb
config.action_mailer.delivery_method = :development config.action_mailer.default_url_options = { host: 'yourappname.c9users.io/', port: $PORT, protocol: 'https' }
チュートリアルのコメント欄には下記のように
config.action_mailer.delivery_method = :development config.action_mailer.default_url_options = { host: '$IP', port: $PORT }
host: $IP
かもしくはhost: '$IP'
にしろ、みたいなことが書いてありましたが、真っ赤な嘘やで。
config/environments/production.rb
config.action_mailer.delivery_method = :smtp config.action_mailer.default_url_options = { :host => 'yourherokuappname.herokuapp.com', :protocol => 'https'}
git origin heroku master
でHerokuへプッシュしたのち、ユーザー登録画面(Deviseを使用しています)から、自分のEmailを登録してみると、メールが届きます(結構時間かかる?それでも数分くらいだったような気も)
おまけ:letter_opener_webを使用して開発環境でのメールの確認
Gemfile
gem 'letter_opener_web', '~> 1.2.0', :group => :development # 私は何もオプション無しで``group :development``内にgem 'letter_opener_web'としました・・・
bundle install # or bundle install --without production
routes.rb
Your::Application.routes.draw do . . if Rails.env.development? mount LetterOpenerWeb::Engine, at: "/letter_opener" end . . end
config/environments/development.rb
config.action_mailer.delivery_method = :letter_opener config.action_mailer.default_url_options = { host: 'yourappname.c9users.io/', port: $PORT, protocol: 'https' }
ユーザー登録後、
https://yourappname.c9users.io/letter_opener
にアクセスすると、認証メールが確認できます。
Day One(Classic)からDay One2へ記事をインポートしてみた
Day One2がセール中だったので購入しました。
記事執筆時点ではまだ半額ですが、そもそも4,800円とか高えよ・・・。
インポートする
まず起動します(当たり前か)
右が新しいDay One2。
イメージ画面?みたいのが出てきますが、ポチポチとContinue
を押していくと、この画面になります。
「リマインダー作ろうぜ!」みたいなこと言われていますが、Classicのほうでも全然使っていなかったので、Continue
を押して進みます。
「インポートするかい?」と出るので、当然Import
を押します。
確認のダイアログが出ます。インポートされた記事はClassicのほうから削除されてしまうわけではないと。
これもImport
を押します。するとインポートが始まり・・・
インポート終了のダイアログが出ますので、OK
を押します。これでインポート終了。簡単でした。
設定をする
メニューバー>Viewです。タイムラインは⌘+1
、カレンダーは⌘+4
と。とりあえずこれだけは覚えておきます。
設定画面です。メニューバーに表示させたいので、Show Menu Bar Entry
を選択。そのGlobal Menu Bar
を使うためのショートカットはデフォルトでCtrl + Shift + D
です。
なんかリマインダーも使えるようにしないといけないらしいですな。
なので、Reminders
タブにて、Enable Reminders
を選択。
これでメニューバーにアイコンが表示されます。
ここをクリックするか、先ほどのショートカットを使用すると
このように出てきて書き込めると。