FactoryGirlで Hashを定義

FactoryGirlでARではなくhashのモックデータを返してほしいときがある。

そういう場合は以下のようにすればよい。

FactoryGirl.define do
  factory :dog, class: Hash  do
    id 1
    name 'john'
    color 'black'

    initialize_with { attributes }
  end
end

initialize_with は初期化処理を定義できるもので、attributesはFactoryGirlのメソッドだけどattributesの戻り値がHashなのでそのまま使っている感じ。

利用するときはいつものようにbuildが使える。

dog = FactoryGirl.build(:dog, name: 'taro')

参考: http://stackoverflow.com/questions/10032760/how-to-define-an-array-hash-in-factory-girl

Capybaraで非表示要素を対象とする

Capybaraで非表示(style="display: none;")になっている要素を検索対象にできないか調べたら、 visibleオプションが使えることが分かった。

例えば、以下のような感じだ

find("#hoeg", visible: false)
have_selector('.hoge', visible: false)
have_css('#hoge', visible: false)

また Capybara.ignore_hidden_elements = falseとすると、visibleオプションを渡さなくても非表示要素が検索対象になる。

なので、以下のようにしてもよい。

before { Capybara.ignore_hidden_elements = false }
after { Capybara.ignore_hidden_elements = true }

参考 http://qiita.com/upinetree/items/4d4022c90ce32b68c38d http://kakakakakku.hatenablog.com/entry/2015/05/14/124653

Slimのスタイルガイド

テンプレートエンジンのSlimのスタイルガイドはないものかと探していたら見つけた。

https://github.com/idmean/slim-style-guide

Slimはシンプルなのでそんなにどう書くか決めなくても大丈夫なんだけど、いくつかは迷うときがある。

例えば属性の定義は以下の3種類が考えられる。

a href="http://slim-lang.com" title='Slim のホームページ' Slim のホームページへ
a[href="http://slim-lang.com" title='Slim のホームページ'] Slim のホームページへ
a(href="http://slim-lang.com" title='Slim のホームページ') Slim のホームページへ

そういったときスタイルガイドは役にたつ。

https://github.com/idmean/slim-style-guide は見てもらうと分かるが、とても納得感があるスタイルガイドとなっている。 しかしいかんせんstar数が少ないので、見て気に入ったらstarを押そう。

API BlueprintについてLTをした

エンジニア飲み会があったので、ちょうど調べていたAPI BlueprintについてLTをした。

スライド↓

API Blueprintとその周辺ツール

API Blueprintは読み書きしやすいのが特徴だ。

JSON SchemaはAPIドキュメントとしてはそのままだと読みにくいし、Swaggerはなんか重厚だし…という人におすすめ。

まあでもSwaggerのyamlは読みやすいよね。 Open API Initiativeで標準フォーマットになったから数あるAPIドキュメントツールの中で数年後生き残るとしたらSwaggerが可能性高いと思う。

JSON Schemaはリクエストやテスト時にデータをチェックしてくれるツールが充実している印象だった。 でもそこまで必要かなー?例えば社内APIだったらそこまで厳密にチェックしなくてもいい気がする。またAPIドキュメントツールに依存し過ぎたくないのでどうにしてもアプリケーション側でデータのチェックすると思うし。テスト時も値の型や構造だけではなく値の内容までチェックするでしょどうにしても。

RAMLはもっと評価されてもよさそうだけどいかんせん後発すぎたのか人気がない…。残念だ。

rack-attack gemでユーザごとにアクセス数を数える

http://shepherdmaster.hateblo.jp/entry/2016/08/21/000115 でも紹介しましたが、 https://github.com/kickstarter/rack-attack という便利なgemがあります。

n秒間にn回アクセスされたらアクセスを弾くThrottles機能を使う場合、 IP単位でアクセス数を数える場合もありますが、ユーザ単位で数えたい場合もあると思います。

そういう場合は以下のようにsessionに入っている(だろう)ユーザidを返せばよいです。

class Rack::Attack
  throttle('req/ip', :limit => 10, :period => 10.second) do |req|
    req.session[:user_id]
  end
end

rack-attack gemで保存先にRedisを指定する

https://github.com/kickstarter/rack-attack という便利なgemがあります。

特定のアクセスのみを許可するSafelists機能や、特定のアクセスを弾くBlocklist機能や n秒間にn回アクセスされたらアクセスを弾くThrottles機能、特定のアクセスを記録するTracks機能等々があり、大変便利です。

で、Throttles機能なんかはアプリケーションサーバーが複数ある場合、アクセス回数を共通ストレージに保存しないと正確なカウントができません。

rack-attack はmemcached と redis が保存先に選べます。 (デフォルトはサーバーのメモリに保存される)

Redisに保存したい場合は以下のように設定すればよいです。

Gemfile

gem 'rack-attack'
gem 'redis-activesupport'

config/application.rb

    config.middleware.use Rack::Attack

config/initializers/rack-attack.rb

class Rack::Attack
  cache.store = ActiveSupport::Cache::RedisStore.new('redis://localhost:6379/0/cache')

'redis://localhost:6379/0/cache' の 0はRedisのDBの番号、 cacheはnamespaceです。

factory_girlでmethodという名前のフィールドをもっているモデルを定義しようとするとエラーになる

method 'GET' みたいに定義するとエラーになる。

その場合は、 add_attribute :method, 'GET' のようにadd_attribute を使うと回避できる。

またmethod以外にもエラーになる名前があって、以下がそのリスト。

__send__
__id__
nil?
send
object_id
extend
instance_eval
initialize
block_given?
raise
caller
method

参考: https://github.com/thoughtbot/factory_girl/issues/666