定期購読しているWeb+DB Press vol.82 ”切りひらくRuby”を読んで知りました。(俺はタバコ吸わないので仕事の休憩時は適当に置いてある雑誌を読む)

今はbrewで入るみたい。rbenvとruby-buildに依存してるからこれからrbenv入れる時はこっちを入れれば一発で全部入りますな。

$ brew install rbenv-default-gems
$ vi ~/.rbenv/default-gems
bundler
rbenv-rehash

中身はbash scriptで俺の知らないテクがたくさんあってよくわかんなかった。

プロジェクト内で単数形と複数形が混在してて気になった。thoughtbotのprojectを幾つかみたけどみんなfactories.rb1ファイルに全部書いてた。

$ rails g factory_girl:model user
	create	spec/factories/users.rb

複数形で書きましょう。

capybara-webkitのバージョンをアップしたら下記のエラー。

dyld: Library not loaded: /usr/local/lib/libpng15.15.dylib
  Referenced from: /usr/local/lib/QtGui.framework/Versions/4/QtGui
  Reason: image not found

capybara-webkitはメジャーバージョンが上がったので依存するライブラリも大きく上がったようだ。(多分今までのqt4はlibpng12を使ってたんだろう)

$ brew update && brew upgrade
$ brew reinstall qt4
$ brew reinstall lbpng

動いた。

commentableとかcategorizableとかconcern名になるようなアレって何て言うんだろう?

そういう処理が数カ所出てきたのでgemにしました。

komagata/availablizer

こういう感じになります。

"comment".availablize  # => "commentable"
"read".availablize     # => "readable"
"scare".availablize    # => "scareble"
"category".availablize # => "categorizable"

rubocopデフォには「おい、それはちょっと口うるさすぎるでしょう?」という項目が結構あって、"複数行ブロックの場合は->じゃなくてlambda使え"というのもその一つ。

% rubocop app/models/comment.rb
Inspecting 1 file
C

Offenses:

app/models/comment.rb:11:26: C: Use the lambda method for multi-line lambdas.
  scope :except_blocked, -> {
                         ^^

でもどのルールをオフにしたらこれが許されるのかわからなかったが、-Dをつければルール名も表示してくれるらしい。

% rubocop -D app/models/comment.rb
Inspecting 1 file
C

Offenses:

app/models/comment.rb:11:26: C: Style/Lambda: Use the lambda method for multi-line lambdas.
  scope :except_blocked, -> {
                         ^^

ほう、Style/Lambdaか。

# .rubocop.yml:
Style/Lambda:
  Enabled: false
% rubocop app/models/comment.rb
Inspecting 1 file
.

1 file inspected, no offenses detected

これで心安らかになった。

「assertありゃええねん」

前回のdecoratorのテストのassertをminitest-power_assertに変えてみた。
# Gemfile:
group :test do
  gem 'minitest-power_assert'
end

わざと間違えてみる。

# test/decorators/user_decorator_test.rb:
require 'test_helper'

class UserDecoratorTest < ActiveSupport::TestCase
  def setup
    ActiveDecorator::ViewContext.current = controller.view_context
    @user = ActiveDecorator::Decorator.instance.decorate users(:jean)
  end

  test 'full_name' do
    assert { @user.full_name == 'Hugh Jackman' }
  end
end
$ rake test test/decorators/user_decorator_test.rb
Run options: --seed 52969

# Running:

F

Finished in 0.134274s, 7.4475 runs/s, 7.4475 assertions/s.

  1) Failure:
UserDecoratorTest#test_full_name [/Users/komagata/code/active_decorator-test_unit/test/decorators/user_decorator_test.rb:10]:

    assert { @user.full_name == 'Hugh Jackman' }
             |     |         |
             |     |         false
             |     "Jean Valjean"
             #<User id: 758109964, first_name: "Jean", last_name: "Valjean", website: "http://jeanvaljean.com", created_at: "2014-07-01 15:35:12", updated_at: "2014-07-01 15:35:12">

1 runs, 1 assertions, 1 failures, 0 errors, 0 skips

こりゃええ!

怖話はminitestに書き換えつつあるんですが、Bizerでは他の開発者に気を使ってrspecを使っています。

Bizerをrails4.1に上げたので、「ヒャッハー、デフォルトでtravel_toが使えるからtimecop削除できるぜー!」と思ったのですがrspecじゃそのままじゃ使えない。(クソがぁ

Before:

it 'coupon is expired.' do
  # FIXME: travel_to in rails 4.1
  Timecop.travel(2014, 5, 10, 0, 0, 0) do
    expect(expired_coupon_user.free_by_coupon?).to be_false
  end
end

After:

# spec/spec_helper.rb:
RSpec.configure do |config|
  config.include ActiveSupport::Testing::TimeHelpers
end
it 'coupon is expired.' do
  travel_to Time.new(2014, 5, 10, 0, 0, 0) do
    expect(expired_coupon_user.free_by_coupon?).to be_false
  end
end

今までTime.nowDate.todayを内部で使うメソッドはテストしやすいように

def metrix(now = Time.now); ... end

みたいに書いてたんですが、デフォルトで気軽にtravel_toが使えるならやらなくていいかな!

C-t: カーソル部分のタグにジャンプ

C-o: 前いた場所に戻る(tagに限らずいつも使いまくるヤツ)

g C-t: タグ候補が複数ある場合に候補一覧を表示

この3つだけでクッソはかどる

Xcodeとかの機能がうらやましい

IDEでは当然の機能ですが、クラスやメソッドの定義に飛べるのって便利ですよね。vimやemacsでは設定すればできるんだろうけどやってる人あんまり見ない。

開いてるbuffer内のものしか飛べないとか、明示的にtag生成コマンド実行とか論外。

そんな折、Gemfileのgemを含めて保存時自動tag生成してくれるvim-tagsというpluginがとても良かったのでご紹介。

szw/vim-tags

vim-tagsの設定

$ brew install ctags
# ~/.vimrc:
Bundle 'szw/vim-tags'
let g:vim_tags_project_tags_command = "/usr/local/Cellar/ctags/5.8/bin/ctags -f tags -R . 2>/dev/null"
let g:vim_tags_gems_tags_command = "/usr/local/Cellar/ctags/5.8/bin/ctags -R -f Gemfile.lock.tags `bundle show --paths` 2>/dev/null"
set tags+=tags,Gemfile.lock.tags

macデフォのctagsはbsdで色々違うのでbrewで入れてfullpath指定。

ファイル保存時にtagsファイルを生成。ちょっと遅くなるので非同期実行するvim-dispatch pluginとの連携も試してみたいと思います。

tpope/vim-dispatch

とにかく機能が細かくgemに分割される昨今。これははかどる!

EngineYardCloudのEnvironmentをのぞいてみたらruby2.1.2に対応してたので怖話をアップデートしました。

stackのversionが上がる時ほど警戒は必要無いとは思いますが、clone environmentしてそちらをアップデートしてみて動作確認してから本アップデートをかけるのが正義。

ruby2.0.0-p247からのアップデートだったんですが、何の問題も無く完了しました。最新は気持ちいい。

Early AccessにはWebサーバーのpumaも来てるのでrails4.1系にしてpumaが正式版になったらこっちも変えたらかなり速くなるんじゃないかなと期待しております!

railsでいつも下記のようにしてたのでgemにしました。

# lib/seed_helper.rb:
require 'active_record/fixtures'
                               
module SeedHelper              
  def import_fixture(name)
    puts "Import #{name}..."   
    ActiveRecord::FixtureSet.create_fixtures \
      "#{Rails.root}/db/fixtures", name
  end                          
end
# db/seeds.rb:
require 'seed_helper'
include SeedHelper # この2行がウザい

import_fixture :users
import_fixture :posts

seed系のgemはたくさんあるけど俺にはどれもオーバースペックだったので。

simple_seed

komagata/simple_seed

使い方

$ mkdir db/fixtures
$ vi db/fixtures/users.yml
user_1:
  name: Jean Valjean
user_2:
  name: Bishop Myriel
user_3:
  name: Cosette
$ vi db/seeds.rb
import_fixture :users
$ rake db:seed
Import users...