LoginSignup
24
22

More than 5 years have passed since last update.

Rails の開発で知っとくと便利な関数

Last updated at Posted at 2016-04-30

実際の開発で知ったことやレビューでよく指摘を受ける事を備忘録を兼ねてメモ。
動作はRuby2.3.1とRails4.2.6で確認。

tryメソッド (ActiveSupport)

みんな大好き(なハズ)tryメソッド。
Rails開発では、viewでモデルインスタンスの値を返す場面などで大活躍します。

[1] pry(main)> user = User.find_by(id: 9999)
=> nil
[2] pry(main)> user.try(:name)
=> nil
[3] pry(main)> user.name
NoMethodError: undefined method `name' for nil:NilClass

viewでNoMethodErrorが発生すると500エラーページが出てしまうので、それを予防するためによく使います。

mapメソッドの&修飾詞

配列の値全部に処理を入れたい場合など、業務のちょっとしたかゆい場面で活躍します。

# 数値配列の中身を文字列に変換したい場合
[1] pry(main)> [2, 4, 6, 8].map(&:to_s)
=> ["2", "4", "6", "8"]

# 複数のUserインスタンスからnameのみを抽出する
[2] pry(main)> users = User.where(id: [1,2,3])
[3] pry(main)> users.map(&:name)
=> ["ほげ1", "ほげ2", "ほげ3"]

pluckメソッド (ActiveRecored)

今年になってから知ったメソッド。
map(&:hoge)とかで抽出していたけど、どう考えてもこっちの方が良かった。

[1] pry(main)> User.where(id: [1,2,3]).pluck(:name)
=> ["ほげ1", "ほげ2", "ほげ3"]

# 複数項目も可能
[2] pry(main)> User.where(id: [1,2,3]).pluck(:id, :name)
=> [[1, "ほげ1"], [2, "ほげ2"], [3, "ほげ3"]]

transposeメソッド

このメソッドは配列を行列に見立てて、行と列を入れ替える動きをする。
応用する事で2つの配列の1つをkey、もう1つをvalueとしたHashを作れる。

[1] pry(main)> hash_keys = %w(2 4 6)
=> ["2", "4", "6"]
[2] pry(main)> hash_values = %w(a b c)
=> ["a", "b", "c"]
[3] pry(main)> hash = Hash[ [hash_keys, hash_values].transpose ]
=> {"2"=>"a", "4"=>"b", "6"=>"c"}

# valuesをModelインスタンスにすると任意のkeyを持ったhashを作れる
[1] pry(main)> hash_keys = %w(a b c).map(&:to_sym)
=> [:a, :b, :c]
[2] pry(main)> hash_values = User.where(id: [1,2,3])
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, 3)
=> [#<User:0x007f9dcf9a99c0 id: 1, name: "ほげ1">, #<User:0x007f9dcf9a9538 id: 2, name: "ほげ2">, #<User:0x007f9dcf9a90b0 id: 3, name: "ほげ3">]
[3] pry(main)> hash = Hash[ [hash_keys, hash_values].transpose ]
=> {:a=>#<User:0x007f9dcf9a99c0 id: 1, name: "ほげ1">, :b=>#<User:0x007f9dcf9a9538 id: 2, name: "ほげ2">, :c=>#<User:0x007f9dcf9a90b0 id: 3, name: "ほげ3">}
[4] pry(main)> hash[:b]
=> #<User:0x007f9dcf9a9538 id: 2, name: "ほげ2">

split(//)メソッド

splitメソッド自体は普通に使われると思うが、引数に//を渡すと文字列を1文字区切りの配列にしてくれる。

[1] pry(main)> "abcde".split(//)
=> ["a", "b", "c", "d", "e"]

# マルチバイト文字にも対応
[2] pry(main)> 'あいうえお'.split(//)
=> ["あ", "い", "う", "え", "お"]


### 別件になるけど、この記事のためにsplit関数を調べていた気づいた事

# 1. 区切り文字に半角スペースを渡すとタブ文字や改行でも区切ってくれる
[3] pry(main)> "ab cd\tef\ngh".split(' ')
=> ["ab", "cd", "ef", "gh"]

# 2. 恥ずかしながらsplitに第二引数があることを知らなかった
[4] pry(main)> "abcde".split(//, 3)
=> ["a", "b", "cde"]

group_byメソッド

便利なのに自分の周りではイマイチ使われない気がするメソッド。
抽出したデータをさらに区分けしたい場合などに便利です。

# 抽出したユーザ情報を性別で分ける
[1] pry(main)> User.where(id: [1,2,3]).group_by{|u| u.sex == 1 ? :male : :female}
=> {:male=>[#<User...(以下略)>], :female=>[#<User...(以下略)>]}

# with_indexを利用して配列のindexをkeyとしたhash化も
[2] pry(main)> %w(a b c d).group_by.with_index{|v,i| i}
=> {0=>["a"], 1=>["b"], 2=>["c"], 3=>["d"]}

# Modelから抽出した際の順番を保持したい場合などにも便利
[3] pry(main)> users = User.where(id: [1,2,3])
[4] pry(main)> users.map(&:id).group_by.with_index{|v,i| i}
=> {0=>["ほげ1"], 1=>["ほげ2"], 2=>["ほげ3"]}

使いドコロが難しいけど、上手く使うと余計なループや分岐が減らせます。

grepメソッド、grep_vメソッド (grep_vはRuby2.3〜)

Ruby2.3で追加されたgrep_vメソッドをキッカケに知ったメソッド。
これを使ってリファクタリング出来そうな箇所が結構あるな。。。

# 配列の各要素に対し、正規表現で一致する要素を配列で返す
[1] pry(main)> %w(hoge piyo hogege bar hogegege).grep(/\Ahoge/)
=> ["hoge", "hogege", "hogegege"]

# ブロックを渡すと、正規表現に一致する要素に対し実行した結果を返す
[2] pry(main)> %w(hoge piyo hogege bar hogegege).grep(/\Ahoge/){|r| r.to_sym}
=> [:hoge, :hogege, :hogegege]

# Ruby2.3で追加されたgrep_vは、正規表現に一致しない要素を返す
[3] pry(main)> %w(hoge piyo hogege bar hogegege).grep_v(/\Ahoge/)
=> ["piyo", "bar"]

between?メソッド (Comparable module)

日付や数値などで範囲判定したい場合に使うと楽できる・・かもしれない。
仕事ではGWや年末年始などの日付判定に使っています。

# GWの判定ロジック(2016/04/29〜2016/05/08)
[1] pry(main)> Time.now.between?(Time.parse('2016/04/29 00:00:00'), Time.parse('2016/05/08 23:59:59'))

SQLの直接実行

便利というかみんな知ってるやり方かと思いきや、意外と若手の子が知らなかったので。

[1] pry(main)> users = ActiveRecord::Base.connection.select_all('SELECT id,name FROM users WHERE id IN (1,2,3)')
   (0.2ms)  SELECT id,name FROM users WHERE id IN (1,2,3)
=> #<ActiveRecord::Result:0x007f9dcf91b7...

# 戻りがActiveRecord::Resultのため扱いが違うので注意
[2] pry(main)> users.each{|u| p u['name']}
"ほげ1"
"ほげ2"
"ほげ3"
24
22
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
22