【備忘録】Railsで使う書き方①~Null条件演算子~
年明けからRubyとRailsを書き始め、気づいたら5ヶ月経過しました。
1日でも早く良いコードが書きたいと思う一方で、なかなか速度が上がらず、毎日悔しい思いをしています。
こうした毎日を過ごしていると次のようなコードを見かけるとすぐに反応するようになりました。
def user_exists?
user = find_user
if user
true
else
false
end
end
こう書き換えたくなります。
def user_exists?
!!find_user
end
また他の言語にも言えることですが、次のような記述を見ると手が止まりません。
numbers = [1,2,3,4,5]
new_numbers = []
numbers.each { |n| new_numbers << n * 10 }
こう書き換えたくなります。
numbers = [1,2,3,4,5]
new_numbers = numbers.map { |n| n * 10 }
これくらいであればすぐに書き換えは思い浮かぶのですが、
なかなか書き換えが思い浮かばず時間を浪費することが多々あります。
今回はその時に使用したいイディオムをまとめたいと思います。
&.演算子
定番ですね。
def find_currency(country)
currencies = { japan: 'yen', us: 'dollar', india: 'rupee'}
currencies[country]
end
def show_currency(country)
currency = find_currency(country)
if currency
currency.uncase
end
end
このshow_currency
メソッドは次のように書き換えることができます。
def show_currency(country)
currency = find_currency(country)
currency&.uncase
end
次のように色々な記事がありますが、
今回の場合だと、currency
にnil
が入った場合、uncase
は
undefined method `uncase' for nil:NilClass (NoMethodError)
が発生します。これに対して$.演算子を使ってuncase
を呼び出すと、uncase
を呼び出したオブジェクトがnil
でない場合は、その結果(今回は大文字)を、nil
だった場合はnil
を返します。
使用例
実際に使用した例は次のようなRailsのmodelに定義したクラスメソッドのケースです。
class Book
def self.expensive(price)
where(price > 3000)
end
end
Book.expensive(price)を呼び出し、該当しない場合は戻り値はnil
になります。
この時Book.expensive(price).order(id: :desc)
と書くとエラーになります。
これを避けるためにBook.expensive(price)&.order(id: :desc)
と書きました。
ちなみに
class Book
scope :expensive, -> { where("price > ?", 3000) }
end
クラスメソッドではなくscopeで定義した時、結果がnil
となった場合は、
該当Scopeの検索条件を除外したクエリが発行されます。
色々と覚えることが多くて大変です。
Discussion