Deviseでユーザー登録後のリダイレクト先を変更する
Deviseのカスタマイズに少し苦労しました。
大体標準通りに使えば問題ないのかもしれませんが、少し加工しようとするとちょっと調べないといけないですね。
今回行うことは、Deviseでユーザー登録後に、Thanksページに飛ばすことです。
リダイレクト自体は割と簡単なのですが、コントローラーにアクションを追加するのに手間取りましたorz
コントローラーをカスタマイズする
今回のDeviseはユーザーモデルをベースとして考えています。
まずはカスタマイズするために、下記のコマンドを打ち込みます。
rails generate devise:controllers Users
これでテンプレートが作成されるかと思います。
変更するコントローラーはclass Users::RegistrationsController < Devise::RegistrationsController
になります。
thanksアクションを入れます。
class Users::RegistrationsController < Devise::RegistrationsController # before_action :configure_sign_up_params, only: [:create] # before_action :configure_account_update_params, only: [:update] # GET /resource/sign_up # def new # super # end # POST /resource def create super end # GET /resource/edit # def edit # super # end # PUT /resource # def update # super # end # DELETE /resource # def destroy # super # end # GET /resource/cancel # Forces the session data which is usually expired after sign # in to be expired now. This is useful if the user wants to # cancel oauth signing in/up in the middle of the process, # removing all OAuth session data. # def cancel # super # end def thanks end # protected # If you have extra params to permit, append them to the sanitizer. # def configure_sign_up_params # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) # end # If you have extra params to permit, append them to the sanitizer. # def configure_account_update_params # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) # end # The path used after sign up. # def after_sign_up_path_for(resource) # super(resource) # end # The path used after sign up for inactive accounts. # def after_inactive_sign_up_path_for(resource) # super(resource) # end end
routesを設定する
ここが少し戸惑いました。
devise_for :users, controllers: { registrations: 'users/registrations' }
上記を追加して、registrationsの動作をusers/registartions
に設定します。
次に、アクションをthanksページのroutesを追加します。
devise_scope :user do get 'users/thanks' => 'users/registrations#thanks' end
devise_scope
で設定しないと、request.env[“devise.mapping”]でroutesの設定がされません。
def devise_scope(scope) constraint = lambda do |request| request.env["devise.mapping"] = Devise.mappings[scope] true end constraints(constraint) do yield end end
こんな常識知らないよって感じですが、設定しましょう。
ユーザー登録後のリダイレクト先を変更する
def after_inactive_sign_up_path_for(resource) users_thanks_path end
users/registaration
でコメントアウトされていると思います。
ここに追加すれば終わりです。
まとめ
ドキュメントとソースコードを見よう。
find_by_カラム名のメソッドが動的に生成されていたという事実
例えば、Fooモデルにtitleというカラムがあるとする。
Foo.find_by(titile: "foo") Foo.find_by_title("foo")
下でも検索できる。
いつも上ばっかり使っていたので、下のパターンがあるとは知らなかった。
補足
rubocop的には上の方がいい。
Class: RuboCop::Cop::Rails::DynamicFindBy — Documentation for rubocop (0.49.1)
rails-syle-guide的に非推奨なので。
ttyとptsについて
dokcer runのオプションで意味不明だったので、調べていました。
docker run -it ←こいつ
% docker run --help -i, --interactive Keep STDIN open even if not attached -t, --tty Allocate a pseudo-TTY
ここでTTYが出てきました。
TTYとは
ttyとは、標準入出力となっている端末デバイス(制御端末、controlling terminal)の名前を表示するUnix系のコマンドである。 元来ttyとはteletypewriter(テレタイプライター)のことを指す。
ターミナルで打つとこうなります。
% tty /dev/ttys004
実際にターミナルで打っている端末の情報ですね。
よくある遊びです。
ここでターミナルを別のウィンドウで立ち上げます。
% tty ←ターミナル1 /dev/ttys004 % tty ←ターミナル2 /dev/ttys006 ターミナル1のウィンドウから下記コマンドを実行する % echo "Hello tty" > /dev/ttys006 % Hello tty←ターミナル2
これを実験するとどういうものかわかりやすいと思います。
pts
ptsはsshでログインした時の端末の情報です。
tty /dev/pts/0
ということは、誰かがsshで同時接続していた場合に、相手をびっくりさせることができますね。
【参考】
ローカル環境のURLをlocalhost以外にする方法
localhost
ってださいなって思う時があるじゃないですか?
そんな時に名前をhostを変える方法です。
/etc/hosts
があると思います。
この設定ファイルに付け足します。
127.0.0.1 foo.com
これでrails s
するとhttp:foo.com:3000
でアクセスできます。
:3000
がいるのはポートの関係ですね。
こうすると、「こいつわかってるやつじゃね?」って感じられそう。
以上です。
CSVでファイルを保存するなら、jsonで保存する方が楽ということに気づいた
CSVでhashの値を保存する場合分解しないといけないじゃないですか?
めんどくさいですよね。
例えばこういうデータです。
class FooApi HEADER = %w(foo bar baz) def export CSV.open('foo.csv', 'w:utf-8', headers: HEADERS, write_headers: true, force_quotes: true) do |csv| results.each do |result| line = [ result[:foo], result[:bar], result[:baz] ] csv.puts line end end end private def results [ { foo: 1, bar: 2, baz: [1, 2] }, { foo: 3, bar: 4, baz: [3, 4] }, ] end end
これよりももっとカラムが増えることなんて多いですよ。
HEADERとか考えるのめんどくさいなって思いました。
そこでjsonで書き出せば何も考えなくていいことに気づきました。
def export FIle.open('foo.json', 'w') { |f| f.puts results } end
これで全てが終わります。
def import @x = open('foo.json') {|f| JSON.load(f)} end
JSONの場合、keyがStringになって嫌だ!ってことがあると思います。
そんな時のためのwith_indifferent_access
です。
ActiveSupport
頼みになりますが、これでアクセスできるようになります。
@x.map!(&:with_indiffrent)access)
もちろん、クライアントによってはjson
って何?ってお客さんも多いでしょう。
ただ、自分の作業やjson
の意味がわかる人なら、ガンガン使うべきだなって思いました。
以上です。
正規表現で〜から〜までのパターン
こういうやつです。
宮藤官九郎(第1話、第2話、最終話)
で名前と後ろを分けたい場合。
(?<name>.[^((]*)(?<supplement>.*)?
否定を間に挟んで、それ以外までにする。
これがミソ。
このパターン多いと思うし、覚えておこ。
正規表現で名前付きキャプチャが便利だった
これがあれば何にマッチさせているかわかるじゃん!って感動しました。
正規表現でキャプチャするときに$1
で変数格納されますが、この場合何にマッチさせているのかがわかりづらいときがあります。
何より量が増えてくるとしんどいです。
使い方
(?<name>正規表現を書いてください)
サンプルです。
text = ["塚本連平(MMJ)", "小松隆志(MMJ)", "六車俊治(テレビ朝日)"] text.split(/\s/).map do |director| m = director.match(/(?<name>.*)(?<organization>(.*))/) { name: m[:name], organization: m[:organization] } end => [{:name=>"塚本連平", :organization=>"(MMJ)"}, {:name=>"小松隆志", :organization=>"(MMJ)"}, {:name=>"六車俊治", :organization=>"(テレビ朝日)"}]
何をやっているのかがわかりやすいです。
$1
よりも圧倒的にやりやすい。
今後とも使っていきます。
rubyでeach_with_indexでindexの値を0以外から始める方法
rubyでeach x indexをしたいパターンが多いです。
そのために、each_with_index
というメソッドがあります。
each_with_index
こちらは基本的に初期値が0からになります。
array = %w(foo bar baz) array.each_with_index do |x, index| puts "#{index}番目#{x}" end => 0番目foo 1番目bar 2番目baz
1から始めたいという場合は、下記のようにすることで回避できます。
array = %w(foo bar baz) array.each_with_index do |x, index| puts "#{index + 1}番目#{x}" end => 1番目foo 2番目bar 3番目baz
ただ、いちいち+ n
を書かないといけないので、めんどくさいです。
each.with_index
そこで、each.with_index
を使用します。
こちらは()を入れることで開始位置を指定できます。
array = %w(foo bar baz) array.each.with_index(1) do |x, index| puts "#{index}番目#{x}" end => 1番目foo 2番目bar 3番目baz
まとめ
indexを0から始める場合は、each_with_index
0以外から始める場合は、each.with_index(n)
をするのがいいのかなと個人的には思いました。
ActiveModelでcallbackをする方法
Formオブジェクトを使用していて、まともにActiveModelを使用しました。
ActiveRecordの場合は自動的にcallbackを仕込めるのですが、ActiveModelの場合はどうすればいいのかわからなかったです。
使い方
class WorkForm include ActiveModel::Model define_model_callbacks :save←callbackを定義する before_save :valid_resource←callbackのメソッドを作成する def save run_callbacks :save do←使用する場所を書く ... end end private def valid_resource ...←処理を書く end end
公式に書いてあります。
以上です。
rails5でautoload問題を解決する
やられましたよ。
rails4 → rails5へのアップデートをしていたのですが、lib
pathの配下のものが読まれない。
config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
問題ないだろ。
そう思っていましたよ。
どうやら、この作業が無効になっています。
2.6 production 環境での起動後は自動読み込みが無効になる 今後Railsがproduction 環境で起動されると、自動読み込みがデフォルトで無効になります。
アプリケーションの一括読み込み(eager loading)は起動プロセスに含まれています。このため、トップレベルの定数についてはファイルをrequireしなくても問題なく利用でき、従来と同様に自動読み込みされます。
トップレベルより下で、実行時にのみ有効にする定数(通常のメソッド本体など)を定義した場合も、起動時に一括読み込みされるので問題なく利用できます。
ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。めったにないと思われますが、productionモードで動作するアプリケーションで自動読み込みが必要な場合は、Rails.application.config.enable_dependency_loadingをtrueに設定してください。
ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。
いや、だいぶ影響あるだろ。
みんな使ってますよ!
ということで解決策
config.enable_dependency_loading = true
これはアップグレードガイドに書いていますね。
他にもやり方があります。
参考
危ない危ない・・・。