🙆

railsのhas_many関連付けの拡張を検証

2024/10/19に公開

Railsガイドの4.6 関連付けの拡張で紹介されている、ActiveRecord関連付けの拡張がCampfireで実装されていたので改めて確認した。

確認用のワンライナースクリプトをruby setup.rbで動かす。

# setup.rb

require 'active_record'
require 'sqlite3'

# ロギング
ActiveRecord::Base.logger = Logger.new($stdout)

# データベース接続の設定
ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: 'db/development.sqlite3'
)

# テーブルの作成
ActiveRecord::Schema.define do
  drop_table :books, if_exists: true
  drop_table :authors, if_exists: true
end

ActiveRecord::Schema.define do
  create_table :authors, force: true do |t|
    t.string :name
  end

  create_table :books, force: true do |t|
    t.string :category_id
    t.references :author, foreign_key: true
  end
end


# モデルの定義
class Author < ActiveRecord::Base
  has_many :books do
    def find_by_book_prefix(book_number)
      find_by('category_id LIKE ?', "#{book_number[0..2]}%")
    end
  end
end

class Book < ActiveRecord::Base
  belongs_to :author
end

# データの作成
author = Author.create(name: 'John Doe')
author.books.create(category_id: '12345')
author.books.create(category_id: '67890')

# 使用例
found_book = author.books.find_by_book_prefix('123')
puts found_book.category_id if found_book

found_bookの検索は、author_id(proxy_association.owner)で絞り込まれた状態でのqueryログが流れる。

SELECT "books".* FROM "books" WHERE "books"."author_id" = ? AND (category_id LIKE ?) LIMIT ?  [["author_id", 1], [nil, "123%"], ["LIMIT", 1]]

下記のようにcontrollerにベタで記載しているコードをmodel側に定義する拡張機能が提供されている。

author.books.find_by('category_id LIKE ?', "123")

この機能を利用したことはないが、findだとモデルscopeとの使いどころに迷うので、ownerを起点としたcreate/updateメソッドを利用を想定する。

Discussion