# config/routes.rb:
devise_for :users,
  controllers: {
    registrations: :registrations,
    omniauth_callbacks: 'users/identities'
  } do
    delete 'users/disconnect/:provider' => 'users/identities#disconnect_omniauth_provider', as: 'disconnect_omniauth_provider'
end
$ rake spec
(...)
DEPRECATION WARNING: Passing a block to devise_for is deprecated. Please remove the block from devise_for (only the block, the call to devise_for must still exist) and call devise_scope :user do ... end with the block instead. (called fr)

上記のようにdevise_forにblockを渡すスタイルはDEPRECATEDになった。

# config/routes.rb:
devise_for :users, controllers: {
  registrations:      :registrations,
  omniauth_callbacks: 'users/identities'
}

devise_scope :user do
  delete 'users/disconnect/:provider' => 'users/identities#disconnect_omniauth_provider',
    as: 'disconnect_omniauth_provider'
end

こんな感じでblockに渡してた部分はdevise_scopeを使うといいらしい。

undefined method `render_partial_with_logging'というエラーが時々出る。調べてみるとkaminariのthreadsafe系のissueが上がってた。ちょうどrails4アプリのweb serverをpumaにした所だったのでまさにコレっぽい。(heroku + rails4のアプリをpumaにしたらかなり速くなった)

undefined method `render_partial_with_logging' for class `#<Class:0x617ead84>' org/jruby/RubyModule.java:2256:in `alias_method' · Issue #214 · amatsuda/kaminari

上記のissueが修正されたのが4 months ago、kaminari最新の0.14.1がリリースされたのが去年。masterを指定するのは怖いので最後のcommitのrefを指定してアップ。

# Gemfile:
gem 'kaminari',
  git: 'git://github.com/amatsuda/kaminari.git',
  ref: '2ed8adfe378594ae1585ac4a457a6d01f04478eb'

railsでscopeを色々チェインする時にそういや二回joinしたらどうなるんだろうと思ってやってみた。(rails4)

>> User.joins(:events).to_sql
=> "SELECT \"users\".* FROM \"users\" INNER JOIN \"events\" ON \"events\".\"user_id\" = \"users\".\"id\""
>> User.joins(:events).joins(:events).to_sql
=> "SELECT \"users\".* FROM \"users\" INNER JOIN \"events\" ON \"events\".\"user_id\" = \"users\".\"id\""

ホッ、変わらないみたい。

herokuでsmtpを使うためにsendgrid addonを入れる。(smtpにgmailを使う場合は要らない)

$ heroku addons:add sendgrid:starter
# config/environment.rb:

(snip)

ActionMailer::Base.smtp_settings = {
  :address        => 'smtp.sendgrid.net',
  :port           => '587',                                                                                            
  :authentication => :plain,
  :user_name      => ENV['SENDGRID_USERNAME'],                                                                         
  :password       => ENV['SENDGRID_PASSWORD'],                                                                         
  :domain         => 'heroku.com',
  :enable_starttls_auto => true
}
# config/initializers/exception_notification.rb:
AppName::Application.config.middleware.use ExceptionNotification::Rack,
  :email => {
    :email_prefix => "[AppName] ",
    :sender_address => %{"notifier" <notifier@example.com>},
    :exception_recipients => %w{komagata@example.com}
  }
# Gemfile:
gem 'exception_notification'
# config/environments/production.rb:

(snip)

  # config.action_mailer.raise_delivery_errors = false
  config.action_mailer.raise_delivery_errors = true

(snip)

  config.action_mailer.perform_deliveries = true
end
$ gem install icalendar
requre 'icalendar'

calendar = Icalendar::Calendar.new                                                                                 
event = Icalendar::Event.new                                                                                       
event.start = Date.new(2013, 7, 1)
event.end = Date.new(2013, 7, 8)
event.summary = "Foo Festival"
event.description = "Greatest event in the world."
event.location = "Hatsudai Tokyo Japan"
calendar.add_event(event)

puts calendar.to_ical

railsでリンクをクリックしたらiCalファイルダウンロード → iCal起動+登録ってやりたい場合。

class FooController < ApplicationController
  def calendar
    calendar = Icalendar::Calendar.new

    # implementation...

    headers['Content-Type'] = 'text/calendar; charset=UTF-8'
    render :inline, layout: false, text: calendar.to_ical
  end
end
$ heroku labs:enable user-env-compile

これすると行ける。理由はわからん・・・。

jenkins, rspec-railsの場合。

# Gemfile:
group :test do
  gem 'ci_reporter'
end

Rakefileの最終行に下記を追加する。

# Rakefile:
require 'ci/reporter/rake/rspec'

rake specの代わりにrake ci:setup:rspec specを実行するとspec/reports/以下にテスト結果のxmlができるので.gitignoreに追加しとく。

spec/reports/

jenkinsの設定

Build時にrake ci:setup:rspec specでxmlが出力されるようにしておく。怖話ではこんな感じ。

bundle install --binstubs
cp config/database.example.yml config/database.yml
rake db:migrate
rake ci:setup:rspec spec

Post-build Actions > Publish JUnit test result reportを追加し、spec/reports/*.xmlを入力。JUnitがこういうxml出すみたい。

下記のようなグラフが出るようになる。怖話ではこんな感じ。

画像を直リンできるので目につきやすいところに貼るのがいいかも。

東アジアの文字幅を取るeastasianwidthを以前npmに上げましたが、やっぱり怖話で使えそうなので文字列の幅を数字で取るメソッドを追加しました。(半角は1、全角は2みたいに)

javascriptで東アジアの文字幅を取得する - komagata

Ambiguous(曖昧)も含めて東アジアの文字列を考慮した感じで取ります。色んな環境で画面が崩れるようなのでもちゃんと取れるはず。

なんでこんなのが必要なのかというと、要は文字の折り返しを自前で実装するときに、monospaceのフォントで全角分幅を取るのか、半角分幅を取るのかを厳密にわかる必要があるからです。

komagata/eastasianwidth · GitHub

npmで作りましたが結局railsで使うのでgemも作りました。

komagata/eastasianwidth-rails · GitHub

スマホのonclick遅い問題(代わりにtouchstart使う)用のライブラリ、fastclickが定番っぽいので勝手にfastclick-rails作っときました。デフォルトでこうなってほしい。

komagata/fastclick-rails · GitHub

使い方

# Gemfile:
gem 'fastclick-rails'
// app/assets/javascripts/application.js
// require fastclick
# app/assets/javascripts/foo.js.coffee
$ ->
  new FastClick(document.body)

これでスマホの時は勝手にtouchstartになってくれます。300ms違うから体感的にもかなり違う。

HerokuのようにSendGridアドオンを使う。

アドオン画面からSendGridを選び、対象のアプリ/environmentを選んでactivateしておく。

Set it upの内容にしたがってey_configというgemを入れておく。これはEYCと連携した各種サービスのIDとかパスワードとかを良いように扱ってくれる。

メールはsendmailでサラッと送りたい気がするが、EC2上のIPはブロックされてたりするのでSendGridやGmailやSESを使うのが無難なようだ。SendGridは無料プランでは1日200通までなので若干不安ではある。

Set it upに書いてあるようにconfig/environments/production.rbに下記を追加する。

config.action_mailer.delivery_method = :smtp
config.action_mailer.default_charset = "utf-8" # NOT FOUND ON RAILS3.1
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
     :authentication => :plain,
     :address => "smtp.sendgrid.net",
     :port => 587,
     :domain => "yourdomain.com",
     :user_name => EY::Config.get(:sendgrid, 'SENDGRID_USERNAME'),
     :password => EY::Config.get(:sendgrid, 'SENDGRID_PASSWORD')
}

EY::Config.getという部分でサーバー上に良い感じに置かれた設定ファイル(実際には/data/app_name/shared/config/ey_services_config_deploy.yml)から値を読みこんでくれる。

ここで罠なのが、config.action_mailer.default_charsetというメソッドはrails3.1以降は存在しないというところだ。うっかりproductionへデプロイするとサイトがエラーになる。stagingというenvironmentを同じ構成で用意し、試しにデプロイしてみてからの方が無難だろう。