社内勉強会用にいくつかまとめたやつ。
ActionView
distance_of_time_in_words_to_now(from_time, include_seconds = false, options = {})
任意の時間からの差分を表示。(~分、~日)
"#{distance_of_time_in_words_to_now(article.updated_at)}前に更新"
# => "2日前に更新"
number_with_delimiter(number, options = {})
数字に区切り文字を入れてくれる。
"#{number_with_delimiter(12345678)}"
# => 12,345,678
highlight(text, phrases, *args)
textの中でphraseに一致するものがあれば、タグで囲ってくれる。
"#{highlight('You searched for: rails', 'rails')}"
# => "You searched for: <strong class='highlight'>rails</strong>"
ActiveRecord
ActiveRecord::Relation#first_or_create
そのクラスのテーブルの最初の要素があればそれを返し、無いならレコード作成。ブロックで使うと便利そう。
User.where(last_name: 'Elen').first_or_create
# 既にあった場合
# => <User id: 1, first_name: 'Jaeger', last_name: 'Elen'>
# 無かった場合
# => <User id: 2, first_name: nil, last_name: 'Elen'>
ActiveRecord::Relation#first_or_initialize
first_or_create
メソッドと異なり、まだcreateしたくない場合はこっち。
ActiveRecord::Scoping::Named::ClassMethods#scoped
あるクラスの持つ全てのレコードを表したActiveRecord::Relationが欲しい時に使う。all
だとArrayになっちゃうので。
※追記:Rails4.0からは、all
メソッドでActiveRecord::Relationが返るようです。scoped
はdeprecated?
User.scoped.class # => ActiveRecord::Relation
User.all.class # => Array
ActiveRecord::Persistence#toggle
booleanなカラム名を渡すと、trueとfalse入れ替え。
p @user.mail_flg # => true
@user.toggle(:mail_flg)
p @user.mail_flg # => false
ActiveSupport::Concern#included(base = nil, &block)
include
されたら、呼び出し側のクラスのコンテキストで実行される処理をブロックで書ける。
module Hoge
included do
scope :is_hoge, ->{where(hoge: true)}
end
end
ActiveRecord::Batches#find_each(options = {})
あるテーブルの全データ更新バッチ処理など、大量のデータをまとめて処理する時には必ず使うべき。
例えば以下の書き方だと、全ユーザーのActiveRecordオブジェクトの配列がall
メソッドで作られ、メモリ上に展開される
User.all.each do |user|
...
end
find_each
を使えば、デフォルトで1,000件ずつ数え上げを行うので、メモリの使用量を節約できる。
User.find_each do |user|
...
end
※似たメソッドに、find_in_batches
というのもある。
ActiveRecord::Calculation#pluck(column_name)
あるテーブルの特定のカラムを配列にしたいときに使う。
map
を利用するより高速に動作する。
下記のようなよくある書き方だと、内部的に10,000万件のActiveRecordオブジェクトが作られて遅い。
User.order('id DESC').limit(10000).map(&:name)
User.order('id DESC').limit(10000).select(:name).map(&:name)
pluck
を使うことで、ActiveRecordオブジェクトの生成を経由せずに、配列が返る。
User.order('id DESC').limit(10000).pluck(:name)
こちらのブログ記事でパフォーマンス検証をやっているが、map
を使う時と比較してかなり高速になってるのが分かる
http://blog.livedoor.jp/sasata299/archives/51847390.html
※ただし、Rails 3.2以上でしか使えない。
※Rails 3.2では、一度にpluck
できるのは単一のカラムのみ。
=> multipluckというgemで複数カラムいけるらしいです
※追記:Rails4.0からはデフォルトで複数カラムのpluck
が可能(なぜ初めからその仕様にしなかったのか...)
※Web+DBのrails高速化の回に載っていたが、Rails 3.0, 3.1のアプリは、 activerecord-raw-dataというgemを使うことで、同等な効果を得ることができるそう
そのほか拡張など
Object#presence
present?
メソッドの評価結果がtrueのときはselfを、falseの時はnilを返す。
'hoge'.presence # => 'hoge'
[].presence # => nil
# 1 => 2のように、書き方がまどろっこしくなくなる!
# 1
name = params[:name].present? ? params[:name] : 'no name'
# 2
name = params[:name].presence || 'no name'
Object#try
こちらもまどろっこしい書き方が減って良い
# 1
user.name ? user.name : 'no name'
# 2
user.try(:name) || 'no name'
Array#from(position)
positionに渡したインデックスから配列の最後までを返す。
%w( a b c d ).from(2) # => %w( c d )
Array#forty_two
[1, 100].forty_two # => 42
人生、宇宙、すべての答えは「42」なのである。