Railsのいろんなメソッド


社内勉強会用にいくつかまとめたやつ。

## 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](https://github.com/hanzq/multipluck)というgemで複数カラムいけるらしいです
※追記：Rails4.0からはデフォルトで複数カラムの`pluck`が可能（なぜ初めからその仕様にしなかったのか...）

※Web+DBのrails高速化の回に載っていたが、Rails 3.0, 3.1のアプリは、 [activerecord-raw-data](https://github.com/hotchpotch/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」なのである。