全部読むの結構時間かかったけど、知らなかったこと、忘れていたこと結構あったのでそれらをまとめまた。
Chapter1
1-7 読めると便利! Rubyっぽい書き方
この辺りのイディオム、ちょくちょく見るし便利だけどいつも忘れる。
nilガード
number ||= 10 # number || (number = 10) と同じ動き
numberに値が入っていればそのまま、nilなら10を代入する。
ぼっち演算子
&.
をつけてメソッドを呼び出すとレシーバがnilでもエラーが発生しない。
obj = nil # objはnilなのでeachを使おうとするとエラーになる。 obj.each{|x| puts x } NoMethodError: undefined method `each' for nil:NilClass # ぼっち演算子をつけるとエラーにならない obj&.each{|x| puts x } => nil
%記法
# %wは文字列の配列を生成する %w(foo bar piyo) => ["foo", "bar", "piyo"] # %iはシンボル の配列を生成する %i(foo bar piyo) => [:foo, :bar, :piyo]
Chapter3
slimを使う。
下記を追加することで、slimが使える
gem 'slim-rails' gem 'html2slim'
コマンドを実行することで既存のファイルをslimに変換してくれる
bundle exec erb2slim app/views/layouts/ --delete
現職ではvueを使ってるので、slim使ったことなかった。pugみたいなもんか。
i18nでエラーメッセージを日本語にする
下記コマンドでja.ymlを取得してconfig/localesにおく。
wget https://raw.githubusercontent.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml --output-document=config/locales/ja.yml
config/initialilzers/locale.rbに以下を記載する。
Rails.application.config.i18n.default_locale = :ja
リクエストパラメータ
GETでもPOSTでもパラメータの受け取り方をプログラマが区別しなくていいようにparamsが使える。 なんとなく使ってたけど、確かにGETでもPOSTでも同じように使えるのはRailsがやってくれてたのか。
レンダーとリダイレクト
レンダーはアクションに続けてビューを表示すること。リダイレクトはアクションを処理した直後にビューを表示せず別のURLに案内すること。
simple_format
以下のコード、hメソッドでXSS対応をした上で改行を
に変換し、さらに
simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: "div")
Chapter4
バージョンを1つ戻してから1つ上げる。 バージョンが戻ることの確認とかに使う。
bin/rails db:migrate:redo
マイグレーションファイルのupとdown
マイグレーション失敗時に自動で戻せない場合に必要。
add_columnとかの場合の失敗は自動で戻してくれるから不要だけど、カラムにlimit: 30
とか追加する時にはdownも書いておくと戻せる。downがないと例外が発生する。
validateのスキップ
falseを設定することでvalidateをスキップできる。
task.save(validate: false)
persisted?メソッド
オブジェクトがDBに登録されているかどうか確認ができる。
redirect_toのパラメータにmodelのオブジェクト
redirect_toのパラメータにmodelオブジェクトすると、showのページに遷移する。
validatesとvalidateの違い
標準の検証はvalidatesで自前の検証処理はvalidateになる。
パスワードのハッシュ化
has_secure_password
を使うことでパスワードをハッシュ化できる。
使うにはbcrypt(gem)が必要。
has_secure_password
をモデルに記述すると、passwordとpassword_confimartion属性が追加される。
2つの属性が一致した時だけパスワードを登録することができる。
テーブルにはpassword_digestの名前でカラムを用意しておく必要がある。これはhas_secure_password
を使用するときの命名ルールである。
認証のためのauthenticate
authenticate
はhas_secure_password
を記述した時に自動で追加される認証のためのメソッド。引数で受け取ったパスワードをハッシュ化して、オブジェクトに保存されてるdigestと一致するか調べる。
helper_method
コントローラにhelper_methodでメソッドを定義すると、viewからでも呼び出すことができる。
skip_before_action
before_actionをスキップすることができる。
Chapter5
Rspecについて
Rspecは動く仕様書として自動テストを書くという発想で作られてる。Rspecは「テスト」ではなく「Spec」を書くという気持ちが大事とある。 「動く仕様書」か、なるほどなるほど。 とりあえず書くもんだと今まで書いてきたけど、こういうフレームワークの思想みたいなものを知ることで、納得してテストを書いていける。
SystemSpecについて
FeatureSpecの代わりっぽい?、結局SPAでどうやるのか?と調べたらいけそう。 ここを見てみた。 tech.unifa-e.com
弊社ではE2EはRequestSpecしか書いてなかったけど、SystemSpecも導入した方が良いのかな。
visit
特定のURLでアクセスする。ログイン画面にアクセスする場合とかは以下のように記述する。
visit login_path
fill_in
パラメータで指定したラベルがついたテキストフィールドに値を入れる。 以下のように記述する
fill_in 'メールアドレス', with: 'a@example.com'
shared_examples_for
itなどを共通化することができる。
shared_examples_for 'タスクが画面に表示されること' do it { expect(page).to have_content 'タスク' } end
コンソールのサンドボックス
Railsコンソールにサンドボックスあるの知らなかった〜。-s
付ければいいのか
bin/rails c -s
Chapter6
CSRFはシーサーフと読まれることがある。
SQLインジェクションに気を付けるパターン
whereメソッドなどでSQL文字列を直接渡して条件指定するときはSQLインジェクションに気を付ける。 こんな場合
User.where("name = '#{params[:user_name]}'")
こっちにした方がいい。
User.where('name = ?', params[:user_name])
Chapter7
ransackを使うときに気を付けること
modelに以下のコードを入れることで特定のカラムに対してしかクエリーを発行できないようにすることができる。 下のコードは関連を指定できる。[]にすることで意図しない関連を含めないようにする。
def self.ransackable_attributes(auth_object = nil) %w[name created_at] end def self.ransakable_associations(auth_object = nil) [] end
mailcatcher
mailcatcherは送信したメールをブラウザ上で確認することができるgem コンソールから以下のコマンドで使える
mailcatcher
config/environments/development.rbに以下の設定をすると使える
config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: '127.0.0.1', port: 1025 }
ActiveStorage
クラウドサービスにファイルをアップロードしてActiveRecordモデルに紐付けることが簡単にできる。 config/storage.ymlに保存先を設定する。 コメントアウトされているが、AWSやGCSも簡単に設定できる。
Chapter9
redoを習慣にする。
ロールバックできないトラブルを防ぐためにマイグレーションを書いたとき、ロールバックが成功することを確認することが重要。
マイグレーションファイルからアプリケーションコードの参照は避ける。
マイグレーションコードは積み重なっていくのでいつ実行しても同じように動く必要がある。 アプリケーションコードを使用する場合、その内容が変更(モデルにバリデーションが追加されるなど)したらマイグレーションファイルの挙動も変わってしまうため、避けた方が良い。
スキーマキャッシュ
マイグレーションファイルでモデルインスタンスを作成すると、ActiveRecordはスキーマをキャッシュする。同じテーブルに対して連続してマイグレーションを行う場合、キャッシュが効いて意図しない挙動になることがあるので、reset_column_information
でスキーマキャッシュを更新するよう習慣づける必要がある。
Chapter10
共通機能のモジュールのMix-in
RailsでMix-inのモジュールを書く時にはActiveSupport::Concernをextendする。 クラスレベルの拡張を素のrubyに比べて少し書きやすくしてくれる。
SIT
ActiveRecordモデルの継承する場合、継承元と継承先で1つのテーブルに対応づけを行うことをSIT(Single Table Inheritance)と呼ぶ。 対応づけらえるテーブルには継承されたテーブルが必要とするカラムを全部盛り込む必要がある。
複数のモデルがカラム処理は特定処理の専門家を作る
コントローラで2つのモデルを扱う処理の場合、片方のモデルにコードを書くと、他のモデルのデータの依存性を高めるのでよくない。 2つのモデルのデータを扱う専門のクラスを作成して処理を書くと良い。
サブリソース単位でコントローラを分割
コントローラは1つのモデルに対して1つでなければならないわけではない。 サブリソースへの操作を対応する複数のコントローラに分けることができる。
所感
まとめて感じたのは特にviewで使う機能に関する知識が結構欠落していること。 SPAがスタンダードになりつつあるので出番が減ってるのは確かだが、Railsを使って仕事をしていくなら最低限は覚えておかないとなぁとしみじみ思う。 あと、Chapter10は現場でかなり参考になる情報だった。定期的に読みなそうと思う。 いつ買ったのかAmazonの購入履歴で調べたら、買ってから2年も経ってた、、、もっと早く読んどけば良かった。 今年は積読消化を頑張らないと