koheitakahashiのブログ

2020.07.01にプログラマーとして生を受けた私が学んだことや、日常について徒然に書いていきます。

最近学んだ Ruby・Rails のコードを書く時のちょっとしたテクニック

はじめに

2020年7月からプログラマーとして働き始め、それから研修期間の後に9月から案件に入りました。 7月からの5ヶ月弱で、先輩のコードを拝見したり、多くのレビューをいただく中で多くのことを学びました。

今回は、学んだことの中から Ruby・Rails を書く時のちょっとしたテクニックを少し紹介したいと思います。

最近学んだ Ruby・Rails のテクニック

インスタンス変数と nil ガードでキャッシュする

不必要な処理をさせたくない時に、インスタンス変数と nil ガードを使うことでキャッシュすることを学びました。

例えば以下のような last_name メソッドがある時、last_name が呼び出される度に1回1回実行されるため計算量が増えます。

class Person
  def initialize(name)
    @full_name = name
  end

  def last_name
    @full_name.split('_').last
  end
end

つまり、以下では、last_name メソッドが2回 @full_name.split('_').last が実行されます。

kohei = Person.new("kohei_takahashi")
kohei.last_name #=> "takahashi"
kohei.last_name #=> "takahashi"

それが以下のようにインスタンス変数と nil ガードを使うことで同じ Person のインスタンスなら @full_name.split('_').last の処理は1回しか走りません。

class Person
  def initialize(name)
    @full_name = name
  end

  def last_name
    # 以下が変わったところ
    @last_name ||= @full_name.split('_').last
  end
end

kohei = Person.new("kohei_takahashi")
kohei.last_name #=> "takahashi"

Hash のデータを集計やグルーピングしたい

例えば、以下のような hash_1 があるとします。 この時、key の先頭(/ まで、ここではネコやイヌなど)が一致するものの数を集計して、hash_2 のような Hash を作りたいとします。

hash_1 = {
  "ネコ/スコティッシュ・フォールド" => 10,
  "ネコ/アメリカン・ショートヘア" => 5,
  "イヌ/チワワ" => 20,
  "イヌ/柴犬" => 25,
  "トリ/セキセイインコ" => 15
}

hash_2 = {
  "ネコ" => 15,
  "イヌ" => 45,
  "トリ" => 15
}

この時、以下のように Hash をいい感じに使うことで比較的スッキリ書けます。

hash_3 = {}
hash_1.each do |key, val|
  first_key = key.split('/').first
  hash_3[first_key] ||= 0
  hash_3[first_key] += val
end
hash_3

定数を管理するモジュール

Rails のプロジェクトで、例えば以下のように credentials から秘匿情報を読み取っているようなコードがあったとします(basic 認証の秘匿情報を管理しているという設定)。

# application_controller.rb
class ApplicationController < ActionController::Base
  USER_NAME = Rails.application.credentials.basic_authentication[:name]
  PASSWORD = Rails.application.credentials.basic_authentication[:password]

  http_basic_authenticate_with name: USER_NAME, password: PASSWORD
end

以下のような定数を管理するモジュールを作成して、 config/initializers などに置いておくと、スッキリ書くことができます。

# config/initializers/constants.rb
module AppConstants
  BASIC_AUTH_USER_NAME = Rails.application.credentials.basic_authentication[:name]
  BASIC_AUTH_PASSWORD = Rails.application.credentials.basic_authentication[:password]
end

# application_controller.rb
class ApplicationController < ActionController::Base
  http_basic_authenticate_with name: AppConstants::BASIC_AUTH_USER_NAME, password: AppConstans::BASIC_AUTH_PASSWORD
end

最後に

コードを少し綺麗に書くときのテクニックとして、お役に立てれば幸いです。