皆どうやってるんだろう。

僕の場合、debuggerはstep実行が必要で無い限り使わない。(step実行が必要な程難しい問題が滅多に無いので殆ど使ってない)

 railsのdebug系の記事は定期的に上がるけど、実際にdebuggerを使ってるところを見たこと無い。

結局、

puts "@posts: #{@posts.inspect}"
とか、他の出力と混ざって見つけづらいので、
puts "-----------------------------------"
puts @posts.inspect
puts "-----------------------------------"

などと書いてrails sしたconsoleで確認している。loggerを使っても他の出力に埋もれるので結局putsする。もう何年も使ってるのにこれはショボイ気がする。

Ruby on Rails Guidesを見るとTagged Loggingというのがのっている。logにtagを付けてtail -fgrepすれば埋もれないのかも。
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged("BCX") { logger.info "Stuff" }
しかし、いちいちブロックで囲む必要があると面倒でputsしてしまう気がする。

railsのloggerとは別のloggerをAppName.loggerとかに設定してlog/app_name.logに出したりするのがいいのだろうか?

# 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違うから体感的にもかなり違う。