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

朝早く出社するようになった

先週くらいから朝8時くらいに出社するようになった。

きっかけとなったのは以下の記事だ。
http://kitak.hatenablog.jp/entry/2016/07/04/182403

 

なんで朝早く出社しようと思い立ったかというと、

・今の会社は10時出社で昼が12時からなので午前が2時間しかない。もったいない。

・午後は、割り込み作業だったりチャットでメンションが飛んできて対応したり気になったことを調べたりMTGの準備だったり等々で作業が分断されがち。

・基本的にオフィスがうるさい。なのでオフィスが静かな朝か夜は作業が捗る。

・朝8時からくれば4時間はまとまった時間がとれる。昼を13時からとれば5時間もとれる。

・朝から働くと頭がすっきりして集中できるらしい。

・朝早く行くと外が涼しいっぽい。

 

で、実際やってみると確かに朝は頭がすっきりして作業が捗る。オフィスも静かだし。素晴らしい。

 

これを読んだ人は、朝早く起きるなんて自分には無理だなーと思う人もいると思う。

自分も朝起きるが苦手でいつも遅刻しがちだった。

なので今早く起きて出社できてることはほとんど奇跡だ。昔の自分からするとありえない。

たぶんこれは意志の力だと思う。

生産性を上げるためにはどうしたらいいか色々と試し考えた結果、もはや朝早く来るしか方法がないという結論に達し、半ば怒りにも似た感情のもと朝早く起きることができている。

それか年をとって朝起きることがそれほど苦ではなくなった説もある。。

 

まあいずれにせよ、早く起きて仕事するのはみんなが言うように確かに効果がある。

今でも自分が早く起きれていることが信じられないし、来週には元に戻っている可能性もあるが、とりあえず続けていければと思う。 

Railsで生のSQLにテーブル名やカラム名を動的に埋め込みたい場合はquoteメソッドを使おう

Railsでアプリケーション開発をしていると、深淵なる理由で生のSQLにテーブル名やカラム名を動的に埋め込みたいケースが出てくる。

その場合安全だと分かっていてもサニタイズしないでSQLに文字列を埋め込むのは気が引ける。

そういう場合は、 ActiveRecord::Base.connection.quote_table_name('table_name')ActiveRecord::Base.connection.quote_column_name('column_name') が使える。

他にもメソッドがあり、 http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Quoting.html をみるとよい。

#quote_table_name#quote_column_nameをかますとクォートで囲ってくれる。

もし文字列のなかにクォートがあれば以下のようにエスケープしてくれる。

pry(main)> ActiveRecord::Base.connection.quote_table_name('users')
=> "`users`"
pry(main)> ActiveRecord::Base.connection.quote_table_name('users`')
=> "`users```"

Railsで未実行のmigrationを調べたい時はrake db:migrate:statusを使うとよい

本番環境でrake db:migrateを実行する場合、はたしてどのmigrationが実行されるのか確認したくなる場合がある。

その場合、rake db:migrate:statusを実行すると未実行のmigrationが表示されて便利だ。

たとえば、以下のような場合downとなっているのが未実行のmigrationである。

% rake db:migrate:status

database: my_db

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20160704042124  Create users
   up     20160705054353  Create blogs
  down    20160722061711  Create categories

以前はdb/migration/以下のファイルと、dbのschema_migrationsテーブルの中身を比較していたが、こんな便利なコマンドがあったなんてな。。

RSpec Mocksで既存メソッドを上書く

RSpecで既存のとあるメソッドが呼びだされたら特定の値を返したい場合、

allow(model).to receive(:foo).and_return(14)   

みたいにant_returnすればよい。これは有名。

しかし深淵なる理由でメソッドを上書きたい場合がでてくる。テスト中に特定の値を返すのではなくオブジェクトの状態やメソッドの引数の値によって返す値を変えたいといった場合だ。

そういった場合は、 https://relishapp.com/rspec/rspec-mocks/v/3-5/docs/configuring-responses/block-implementation にあるように、

allow(model).to receive(:foo) do |arg|
 # テスト用の実装 
end 

のようにすると既存のメソッドを上書ける。

Railsでtrimするたった一つの冴えたやり方

trimしたいという欲求はアプリケーションを作る上で必ず出てくる。

そしてすぐにString#stripではダメだと気付く。全角スペースが削除されないからだ。 で、独自の正規表現を書いたりするんだけど、ActiveSupport内に便利な定数があるのでそれを使うと楽。

str.gsub(ActiveSupport::Multibyte::Unicode::LEADERS_PAT, '').gsub(ActiveSupport::Multibyte::Unicode::TRAILERS_PAT, '')

LEADERS_PATとか、TRAILERS_PATって何?って思った人は、 http://api.rubyonrails.org/classes/ActiveSupport/Multibyte/Unicode.html をみるか、ソースを見るといい。

要は、以下の文字がtrimされる。

      # All the unicode whitespace
      WHITESPACE = [
        (0x0009..0x000D).to_a, # White_Space # Cc   [5] <control-0009>..<control-000D>
        0x0020,                # White_Space # Zs       SPACE
        0x0085,                # White_Space # Cc       <control-0085>
        0x00A0,                # White_Space # Zs       NO-BREAK SPACE
        0x1680,                # White_Space # Zs       OGHAM SPACE MARK
        (0x2000..0x200A).to_a, # White_Space # Zs  [11] EN QUAD..HAIR SPACE
        0x2028,                # White_Space # Zl       LINE SEPARATOR
        0x2029,                # White_Space # Zp       PARAGRAPH SEPARATOR
        0x202F,                # White_Space # Zs       NARROW NO-BREAK SPACE
        0x205F,                # White_Space # Zs       MEDIUM MATHEMATICAL SPACE
        0x3000,                # White_Space # Zs       IDEOGRAPHIC SPACE
      ].flatten.freeze