1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ActiveRecordのスコープundifined methodになる問題  WhereChain オブジェクトと ActiveRecord::Relation の違い

Posted at

症状

以下のようなコードがあったとします。

Column.published.order_latest.limit(3)

このコードで使用されている scope メソッドは、以下のように定義されています。

scope :order_latest, -> { order(published_at: :desc, created_at: :desc) }
scope :published, -> (current_date = nil) {
  current_date ||= Util::DatetimeUtil.get_instance.get_current_date_time
  where { (is_published == true) & (published_at <= current_date) }
}

上記のコードを実行したときに、以下のようなエラーが発生します。

undefined method 'order_latest' for #<ActiveRecord::QueryMethods::WhereChain>

原因

このエラーの原因は、published スコープが ActiveRecord::QueryMethods::WhereChain オブジェクトを返しているためです。以下の点が問題を引き起こしています。

  1. published スコープで where をブロック形式で使用している: where メソッドをブロック形式で使用すると、返り値が ActiveRecord::QueryMethods::WhereChain になります。
  2. WhereChain オブジェクトと ActiveRecord::Relation の違い:
    • 通常の where メソッドは ActiveRecord::Relation を返します。これにより、orderlimit などのメソッドをチェーンして使用できます。
    • 一方、WhereChain オブジェクトは、複雑な条件を組み立てるためのものです。このオブジェクト自体には orderlimit といったメソッドは定義されていないため、order_latest を続けて呼び出すとエラーが発生します。

具体例

以下のようなコードでエラーが発生するのは、この WhereChainActiveRecord::Relation の違いに起因します。

# これはエラーになる例
Column.published.order_latest

この場合、published が返すのは WhereChain なので、order_latest メソッドが見つからずエラーとなります。

解決方法

このエラーを解決するには、published スコープ内の where を標準の形式に修正し、ActiveRecord::Relation を返すようにします。

修正後のコード

scope :published, -> (current_date = nil) {
  current_date ||= Util::DatetimeUtil.get_instance.get_current_date_time
  where(is_published: true).where('published_at <= ?', current_date)
}

これにより、published スコープは ActiveRecord::Relation を返すようになります。これで、published スコープに続けて order_latestlimit などのメソッドをチェーンすることが可能になります。

修正後の使用例

# 期待通りに動作するようになる
Column.published.order_latest.limit(3)

まとめ

  • where メソッドをブロック形式で使用すると、WhereChain オブジェクトが返り、他のメソッドをチェーンできなくなります。
  • published スコープを修正して ActiveRecord::Relation を返すようにすることで、order_latest などのチェーンが可能になります。

このような問題を避けるためには、where の書き方に注意し、標準的な形式を使用することが重要です。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?