Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7: ActiveRecord::Relationにstructurally_compatible?が追加(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

参考: 週刊Railsウォッチ20210830『ActiveRecord::Relation#structurally_compatible?が追加

Rails 7: ActiveRecord::Relation#structurally_compatible?が追加(翻訳)

Railsの優れている点のひとつは、SQLコードをまったく書かずにデータベースオブジェクトやクエリを簡単に扱えることです。これが可能なのは、Railsのコアライブラリの中で間違いなく最高峰であるActive Recordライブラリのおかげです。

Active Recordクエリインターフェイスを使えば、findgroupjoinsといったさまざまなクエリ操作を実行できます。

また、wherenotor操作を用いてリレーションをチェインすることも可能です。ただしorand操作については、チェインする2つのリレーションに構造上の互換性を持たせておく必要があります。

2つのリレーションに構造上の互換性を持たせるには、両者が同じモデルを対象とし、かつwheregroupが定義されていない場合)またはhavinggroupが存在する場合)だけが異なっていなければなりません。

従来は、2つのリレーションが構造上の互換性を持っているかどうかを簡単に確かめる方法がありませんでした。リレーションの値をイテレーションするか、orandで発生するArgumentErrorをキャッチする必要がありました。

しかし、クエリでorandを実行する前に2つのリレーションが構造上の互換性を持っているかどうかを簡単にチェックできるActiveRecord::Relation#structurally_compatible?がRails 7に追加されました(#41841)。

たとえばPostモデルに :content:user_idstatusという属性があり、Commentモデルに:post_id:user_id:contentという属性があるとしましょう。Posthas_many :commentsを持ち、Commentbelongs_to :postを持っています。

構造上の互換性を持つリレーションが2つあるとします。

  relation_1 = Post.where(status: 'active')
  relation_2 = Post.where(id: current_user.id)

また、構造上の互換性を持たないリレーションも2つあるとします。

  relation_3 = Post.where(status: 'active')
  relation_4 = Post.joins(:comments).where(comments: { user_id: current_user.id})

変更前

これらのリレーション間でorクエリを実行しなければならなくなった場合、ArgumentErrorをキャッチします。

  relations = [[relation_1, relation_2], [relation_3, relation4]]
  relations.each do |relation|
    left = relation.first
    right = relation.last
    begin
      left.or(right)
    rescue ArgumentError
      # 構造上の互換性を持たないリレーションが失敗したらArgumentErrorをrescueする
    end
  end

変更後

Rails 7では、リレーション同士が構造上の互換性を持つかどうかをクエリ実行前にチェックできます。

  relations = [[relation_1, relation_2], [relation_3, relation4]]
  relations.each do |relation|
    left = relation.first
    right = relation.

    if left.structurally_compatible?(right)
      left.or(right)
    end
  end

これは、例外をキャッチせずにリレーションを手軽にクエリできる素晴らしい改善です。このような小さなヘルパー機能が豊富にあるからこそ、Active Recordが優秀なライブラリとなり、Railsフレームワークが開発者にとってより使いやすくなっています。

関連記事

Rais 7のbyebugがruby/debugに置き換わる(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。