bootstrap-sassをbundle updateしても反映されない

twbs/bootstrap-sass · GitHubapplication.scssで読み込んでいるdevelopment環境での話。

$ bundle update

しただけでは、application.cssが更新されないので、古いBootstrapを見てしまう。

$ touch app/assets/stylesheets/application.css.scss 

しても効果なし。
application.css.scssを適当に編集して画面を更新。その後戻したら行けた。

…本番でも起きた。

$ rake assets:clobber assets:precompile RAILS_ENV=production

した。

find_by(nil)を呼んだら警告を出すGem "where_is_nil"

名前はいいの思いつかなかったので仮。

find_by(nil) にハマるで書いたんだけど、またやっちゃう自信があったので、Railsの勉強がてら機械的に防止するGemを作った。

そもそもバグじゃないの?

find_by(nil) returns first record instead of nil · Issue #14867 · rails/rails · GitHub
ということなので、バグじゃない。仕様。

  • nil, 1, '1' => 最初のレコード
  • 'a' => エラー
  • 0 => nil

になる。

where_is_nil Gemは何をするか

find_by(nil)find_by(1)が呼ばれた時に、ログやエラーを出して、find_by(id: 1)の間違いじゃない?と警告します。

設定項目などはGitHubに。
tnantoka/where_is_nil · GitHub

find_byだけで、whereの時はnilでも何もしていない。
(GitHubで検索したらwhere(nil)はたくさん使われてたので。また、当初の目的はタイポ防止で、間違えてwhere(nil)することはあまりなさそうなため)

インストールと設定

# Gemfile
gem 'where_is_nil'

$ bundle

するだけです。

参考にしたGem

Gemは書き慣れてないので、いろいろ参考にさせていただいた。

alfa-jpn/kakurenbo · GitHub
yuki24/did_you_mean · GitHub
airblade/paper_trail · GitHub
plataformatec/devise · GitHub

The Basics of Creating Rails Plugins — Ruby on Rails Guides
公式のガイドもわりと充実してる。

一応動く状態になったので、個人プロジェクトで使っていこう。


以下メモ。

find_by(nil)した時に何が起きてるか

Railsのソースで関連しそうなところ(4.2.0)

find_by/where
arel

処理を追う

find_byはそのまま素通りして、whereになげる。

where内のcase文。
nilの場合はblank?がtrueになるので、selfがそのまま返される。
それがtakeされるので最初のレコードが取得される。

1やid: 1の場合は、where!が呼ばれる。

where_valuesが以下のように更新される。

  • { id: 1 } => [#<Arel::Nodes::Equality>]
  • 1 => [1]

あとはtakeの時にSQLに変換される。そこはarelの処理。

build_arelからcollapse_wheresが呼ばれ、以下のように変換される。

  • { id: 1 } => Equalityのまま変化なし
  • 1 => #<Arel::Nodes::Grouping>

それが、Arel::Nodes::And.newに渡される。

なんだかんだで最終的に、to_sqlされると、

irb> User.where(1).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE (1)"
irb> User.where(id: 1).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 1"
irb> User.where(nil).to_sql
=> "SELECT \"users\".* FROM \"users\""

となる。

後から気づいたけど、↑はrelationなので、whereとかを呼んだ後find_byした時の話。
User.find_byを直接呼んだ場合は、
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/core.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/querying.rb
が呼ばれてる。

最終的には同じ処理を通るのでよしとする。

find_by(nil) にハマる

意図せず、

Team.find_by(session[:team_id])

みたいなコードを書いちゃってた。

本来は、

Team.find_by(id: session[:team_id])

と書きたかった。

後者はsessionに何も入ってないとnilが返ってくるけど、前者は一番最初のレコードが返ってきてしまう。(Team.where(nil).takeになっちゃってるイメージ)

気づきにくくて時間を無駄にした。

ちなみにRailsは4.2。

Rails 4.18 → 4.2.0のアップデート

A Guide for Upgrading Ruby on Rails — Ruby on Rails Guides

$ bundle update rails slim-rails devise
$ rake rails:update

rspecを実行すると、devise関連でmimes_for_respond_torequire_no_authenticationがないというエラーが大量に出た。

, github: 'plataformatec/devise'を追加して最新版を利用。
また、respondersのバージョンが1.0.0だったのでupdate。

$ bundle update responders

serialized_attributesがRails 5でなくなるよというWARNINGはひとまず放置。

あとpaperclipのURLのタイムスタンプがテスト中ずれるという問題があったけど、実害無しなので、タイムスタンプを見ないようにテストを修正。

こんなもんか。

_initDataを定義したらVue.jsがおかしくなった

$dataの初期化を再利用したくて、_initData()というメソッドを定義したら、呼び出してないところでも呼ばれて変になった。

おや?と思って、Vueのソースを見てみると、_initで始まるメソッドがいくつか内部で利用されていた。

いちいち確認するのも面倒だし、__(2個)とかで始める方がいいかな。(_をつける理由は、Privateなメソッドだとわかりやすいようにしたいだけなので、特にこだわりはない。)