2015/12/16

Railsのテストで定数のスタブが欲しい場合

Railsの ActiveSupport::TestCase は minitest を使っていて、minitest/mock には定数をスタブ化する機能はない。
adammck/minitest-stub-const ってのはあるけど、外部ライブラリ入れるほどじゃないよねって場合があるかもしれない。
そんな時はこんな感じのコードでいいんじゃないかな?
こういうトリッキーなのは最終手段的なもので、定数を環境ごとに設定ファイルに定義できるような gem を使うべきだとは思う。
やってみたらできたというお話

assert_change

ユニットテスト時によく使うメソッドの1つに assert_difference がありますね。
でもこれ差分を取るので数値を返す式にしか使えません。使おうとしたら + なんて演算子ないよってエラーが出ます。
仕方なしにこんなテストコードを書いてません?
test 'ユーザーが確認済みになること' do
  assert_not user.confirmed?
  # ここに承認処理
  assert user.confirm?
end
それならば、こんなメソッドを test_helper あたりに定義しておいて
test 'ユーザーが確認済みになること' do
  assert_change 'user.confirmed?' do
    # ここに承認処理
  end
end

# 実際の値を気にしなくていいならこんな使い方も
test '保存したら updated_at が更新される' do
  assert_change 'user.updated_at' do
    user.save
  end
end
と書くとちょっとスッキリしますね。コードはほぼほぼ assert_difference のパクリです。
expression の指定方法は必要になったら広げる感じでいいかな。

2015/12/14

jQuery使ってAJAXでファイルアップロード

なんか毎回毎回うろ覚えでちょろちょろ調べながら書いている気がするのでメモとして 今回はdragoverを補足してキャンセルしておかないとdropイベントを補足してくれなかったのにハマった
スタイル変えたり、イベント伝播のキャンセル処理は共通なので class で処理して共通jsに置く。
ドロップされた時の処理は、アップロード先やアップロード後の処理など画面ごとになる可能性が高いので id を使って個別jsに置くイメージ

2015/12/10

Deviseの有効期限設定をテストする

設定ファイル config/initializers/devise.rb はこんな感じとする。
Devise.setup do |config|
  # 省略
  config.reset_password_within = 30.minutes
  config.confirm_within = 30.days
  # 省略
end
テストコードはこんな感じでかけた。 Recoverable では reset_password_sent_at reset_password_within.ago を比較している。
ActiveSupport::Duration#agoまで遡ると初期値である Time.current に対して演算していたので、最初は Time.stub(:current, ... のようにしていた。
しかし、Confirmable では、合算値を Time.now と比較している。そのため、Time.current は通らないのでこのやり方ではだめだった。
結局は Time.now をスタブ化したらよかったわけだが、こういう同質的な処理は同じ書き方をしてほしいなーとおもった昼下がり。

2015/12/09

Deviseにてシステムからユーザーのメールアドレスを変更してもメールを送信しない

Devise を使用していて、手順を踏まずにシステムにてメールアドレスを変更すると保存時にメールが送信されてしまう。
メールを送信したくない場合は skip_reconfirmation! を使用する。 なお、新規作成時に確認手順を飛ばしたい場合は skip_confirmation! を使う。

2015/12/04

ArelでのOR検索ついでにごにょごにょいじってみた

1つのキーワードで複数テーブルの複数カラムをあいまい検索ってよくある話ですね。
Arelを使って OR の LIKE 検索って冗長になりがちだけどそこそこパターン化出来そうだなーとつらつらとコード書いてみた。 実際は SimpleFinder までやると適用できるパターンが限定されるので、04_finally みたいなところが落とし所な気もする。
人によっては 03_inject_with_symbol ぐらいが一番可読性がいいって意見もありそう。
Arelを使って OR や LIKE をするメリットは scope にして merge した時に壊れないって記述をよく見ますが、こういう風に動的に対応箇所を増やせるように持っていくのも楽というのもメリットですね。文字列で where 内を書いていたらなかなかこうはできない
あ、こんな処理を他にもたくさん書かなければいけない場合は Squeel 入れたほうがいいと思います。

全然関係ないけど、gist って編集時はインスタンス変数に色つけてくれるのに閲覧時には色つけてくれないの何でだろ

[追記] たまたま Ruby on Rails Advent Calendar 2015 が空いてたので飛び入りしました。