0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails】DRYなコード

Last updated at Posted at 2023-07-23

DRY原則-二重化の過ち

DRY原則Don't Repeat Yourself = 繰り返しを避けること)

システム内の二重化を最小限に抑えることを目的としている

DRY原則を破るということは、同じ知識を2箇所以上に記述すること。
この場合、片方を変更するのであれば、もう片方も変更しなければいけなくなる。

開発自体の理解とメンテナンスを容易にする唯一の方法は、DRY原則に従うこと。
「すべての知識はシステム内において単一、かつ明確な、そして信頼できる表現になっていなければならない」

既にあるものを簡単に見つけ出して再利用できるようにし、同じものを何度も作成しないような環境を構築すること

重複しているクエリを修正する

最後の条件だけ違うパターン

共通コード.rb
transaction_arel      = Transaction.arel_table
credit_arel           = Credit.arel_table
shop_arel             = Shop.arel_table
shop_association_arel = ShopAssociation.arel_table

# 条件
condition_shop = ... # ここ

credit = Credit
           .joins(:transaction)
           .where(credit_arel[:member_id].eq(nil))
           .where(condition_shop)
修正前.rb
if sample?
  condition_shop = Shop
                     .joins(:shop_associations)
                     .where(shop_arel[:identifier].eq(SAMPLE_IDENTIFIER))
                     .where(shop_association_arel[:shop_id].eq(transaction_arel[:shop_id]))
                     .exists
else
  condition_shop = Shop
                     .joins(:shop_associations)
                     .where(shop_arel[:identifier].eq(SAMPLE_IDENTIFIER))
                     .where(shop_association_arel[:shop_id].eq(transaction_arel[:shop_id]))
                     .exists.not
end
修正案1.rb
shop = Shop
         .joins(:shop_associations)
         .where(shop_arel[:identifier].eq(UNIQLOPAY_IDENTIFIER))
         .where(shop_association_arel[:shop_id].eq(transaction_arel[:shop_id]))

condition_shop = sample? ? shop.exists : shop.exists.not
修正案2.rb
condition_shop = Shop
                   .joins(:shop_associations)
                   .where(shop_arel[:identifier].eq(UNIQLOPAY_IDENTIFIER))
                   .where(shop_association_arel[:shop_id].eq(transaction_arel[:shop_id]))
                   .exists

condition_shop = condition_shop.not unless sample?

Shopモデルに対するクエリの定義が重複せず、コードが簡潔になる。

途中の条件が違うパターン

修正前.rb
if sample?
  contracts = contract_arel
                .project(contract_arel[column_name], contract_arel[:start_date].maximum.as('start_date'))
                .group(contract_arel[column_name])
                .as('contracts')
else
  contracts = contract_arel
                .project(contract_arel[column_name], contract_arel[:start_date].maximum.as('start_date'))
                .where(contract_arel[:start_date].lteq(target_date))
                .group(contract_arel[column_name])
                .as('contracts')
end
修正後.rb
contracts = contract_arel.project(contract_arel[column_name], contract_arel[:start_date].maximum.as('start_date'))
contracts = contracts.where(contract_arel[:start_date].lteq(target_date)) unless sample?
contracts = contracts.group(contract_arel[column_name]).as('contracts')
  • クエリの定義が重複していない。
  • 条件結果の結果に応じてクエリの一部を条件付きで追加している。

関連

0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?