日本の祝日が分かるgem、holiday_jp 0.3.1をリリースしました。

単純なgemなんですが、何故か@pwimさんが高速化してくれたり、@kakutaniさんがリファクタリングしてくれたりで、gemを介して遊んでるみたいな感じです。

今回はjewelerオワコンってことでbundlerにしたり、travis-ciしたり、rubygems-test対応したりしました。

僕も他のgemで新しいツールを使う前の実験台として使ったりしています。:-)

rubygems-testって面白いですね。僕はperl使ってた時に、「cpanの自動テストうっっっz」とか思ってましたが、良い物ですね。すいません。

特にrubygems-testをユーザーがインストールをしてるとプラットフォーム毎にテストが通ったかどうかを自動でhttp://test.rubygems.org/にアップしてくれるのがイカス。

Gem Testers

holiday_jpに幸あれ、rubygems-testに幸あれ。

utf-8のメールをmail.gemを使って送るとWARNINGが出る。

Non US-ASCII detected and no charset defined.
Defaulting to UTF-8, set your own if this is incorrect.

明示的にcharsetを指定すればOK.

# coding: utf-8
require 'rubygems'
require 'mail'

mail = Mail.new do
  to       'foo@example.com'
  subject  'テスト'
  body     'テストメール'
end

mail.charset = 'utf-8' # It's important!
mail.delivery_method :sendmail
mail.deliver

怖話でコメント欄がスパムで埋め尽くされて困ったので日本語が入ってないコメントは弾くようにしました。

「日本語が入ってない場合弾く」というのはMovableTypeの時からあるやり方ですが、イマイチ綺麗に実装できる感がしなくて控えてました。しかしmojiという素晴らしいgemを使ったら簡単に出来ました。

class Comment < ActiveRecord::Base
  validates_format_of :body,
    :with => Moji.regexp(Moji::ZEN_ALNUM | Moji::ZEN_KANA | Moji::ZEN_KANJI),
    :message => I18n.t('errors.messages.not_a_zenkaku')
end

mojiは色々な文字種の正規表現を持っていて手軽に組み合わせたりできます。最初はMoji::ZENで全角文字があればOKにしました。しかし実データ(スパム)にはギリシャ文字やキリル文字が存在していたのでそれも除外するようにしました。

$ rails c -E production
>> Comment.all.each {|c| c.destroy unless c.valid? }

これで今までの全てのスパムが消滅。今のところ新しいスパムも防げてるようでスッキリ。

カウンターキャッシュのリセット

以前、update_countersメソッドを使ってカウンターキャッシュを設定したつもりになっていました。しかし、update_countersメソッドは与えた数だけカウンターが増えるという動作だったようです。代わりにreset_countersメソッドを使えばcomments.countの数にresetしてくれるようです。

Story.all.each do |story|
  Story.reset_counters(story.id, :comments)
end

paperclipを使ってて「縦長の画像をアップしたら横長になる」という問題。

これはpaperclipが悪いんじゃなくて、元のファイルもMacのPreviewで見ると縦長なんだけど、ブラウザで見ると横長。MacのPreview他、ExifのOrientationタグに対応したソフトで見ると縦長に見える。

Webアプリ的にはちょっと困る。「縦長の画像をアップしたら横長になった!」と言われても見てるツールの違いで最初から横長なんだから。

imagemagickのconvertにはExifのOrientationタグの内容に合わせて画像データを回転させてくれる超便利な-outo-orientオプションがあるのでそれを使えばいい。

paperclipはrmagickを使わず、convertコマンドを呼び出すだけで、好きなオプションが渡せるというイカシタ作りになっているのでこんな感じでOK。

class User < ActiveRecord::Base
  has_attached_file :picture, convert_options: {all: '-auto-orient'}
end

allは複数のstyleが合った場合に全部にこのオプションを付けるという指定。originalも残るから安心。

# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  if Rails.env.production?     
    provider :twitter, 'xxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxx'
  else
    provider :twitter, 'ooooooooooo', 'oooooooooooooooooooo'
  end
end

今まで通りだと動きません。test/test_helper.rbに下記を追加。

require 'shoulda/rails'

今βのshoulda 3.xなら大丈夫なのでもうすぐこれも必要無くなるみたいです。

@kakutaniさんからpull requestが来てたので改めて、holiday_jpについて。

2009年に仕事で必要になって作ったgemです。祝日が必要なソフトウェアは結構あると思いますが、こんな調査に時間を割くのは一人でいいんで共有できればと。

祝日は法律によって増えたり減ったりするので未来に渡って計算で算出することができません。

休日・祝日の定義について

休日は単に休みの日です。祝日は”国民の祝日を定める法律”で規定されるお祝いのための休日です (土日は祝日ではありません)。皇室の祭典を行った大祭日などが元になっています。

立春の日・秋分の日について

また厄介なのが立春の日と秋分の日です。基本的には国立天文台の算出する定気法による日(天体の動き)から決定されるため「ほぼこの日だろう」という日は分かりますが、実際には前年度の2月1日に閣議決定され、官報で告知されるまで確かなことはわかりません。(天文学に基づいて年毎に国家の祝日が決定されるのは世界的に見ても珍しいそうです。)

つまり、「現行法に置いては」という但し書きをつけても、日本の祝日は1年先までしかわからないということです。

「1年毎に誰かがメンテナンスする必要があるのであればgithubとかあるし100年分ぐらいgemの中に持っちゃえばいいじゃん。」

ということでholiday_jpができました。

関連:holiday_jp - 国民の祝日が分かるライブラリ - komagata

% rake
`include Capybara` is deprecated please use `include Capybara::DSL` instead.

include Capybaraがdeprecatedになってたので指示通り書き換えました。

# test/test_helper.rb:
class ActiveSupport::TestCase  
  (...)
  class ActionDispatch::IntegrationTest 
    include Capybara::DSL      
    Capybara.app = KowabanaJp::Application
  end
end

Unit::TestとCapybaraでのIntegrationTestは簡単なのにちゃんと動く(バグを見つけたりデグレを防ぐ役割をちゃんと果たすという意味で)のでお気に入りです。

これ便利さがちょっと伝わりづらいんですが、rvmで普段使いのruby(default)用にruby-1.9.2-p290@defaultとか作って指定しておくと@globalが空なので混ざらなくて良いって話。新環境作るたびに$ gem install bundlerする必要あるけど。みんなやってることかも?

Paperclipで画像サイズの最後に使うコレ

has_attached_file :foo, :style => {:thumb => '100x80>'}

いつも意味忘れてググるけどImageMagickのオプションなので下記に書いてある。

Resize or Scaling -- IM v6 Examples

  • Ignore Aspect Ratio ('!')
  • Only Shrink Larger ('>')
  • Only Enlarge Smaller ('<')
  • Fill Given Area ('^')
  • Percentage Resize ('%')
  • Pixel Area Limit ('@')
  • Cropping ('#')

参照:[rails]PaperClipでクロッピング - func09