[Rails] 中間テーブルで並び順を制御したい時におすすめのTips

2023/12/06

Rails

こんにちは。

みなさんRailsで中間テーブルで並び順を制御したい時ってありますよね?

例えば、ユーザーが複数のタグを持つような場合、タグの並び順を制御したい時があります。

そんな時におすすめのTipsを紹介します。

中間テーブルに並び順を持たせる

まずは、中間テーブルに並び順を持たせます。

db/migrate/20211206000000_create_user_tags.rb
class CreateUserTags < ActiveRecord::Migration[7.0]
  def change
    create_table :user_tags do |t|
      t.references :user, null: false, foreign_key: true
      t.references :tag, null: false, foreign_key: true
      t.integer :position, null: false, default: 0

      t.timestamps
    end
  end
end
app/models/user_tag.rb

class UserTag < ApplicationRecord
  belongs_to :user
  belongs_to :tag

  scope :ordered, -> { order(position: :asc) }
end

はい、これで中間テーブルに並び順を持たせることができました。

中間テーブルの並び順で呼び出すようにする

次に、中間テーブルの並び順で呼び出すようにします。

app/models/user.rb
class User < ApplicationRecord
  has_many :user_tags, -> { ordered }, dependent: :destroy
  has_many :tags, through: :user_tags
end
app/models/tag.rb
class Tag < ApplicationRecord
  has_many :user_tags, -> { ordered }, dependent: :destroy
  has_many :users, through: :user_tags
end

これで、中間テーブルの並び順で呼び出すことができました。

解説

ここで、-> { ordered }というのは、scope :ordered, -> { order(position: :asc) }を呼び出しているだけです。
Railsのrelationでは、lambdaでscopeを呼び出すことができます。

Active Record の関連付け - Railsガイド

これをしておくことで、中間テーブルの並び順で呼び出すことができます。

大きなアプリケーションでも、user.user_tags.ordered.map(&:tag)のようなコードが書かれていたりするので、このような書き方をしておくとシンプルに書けるよーというTipsでした。

今回はこのあたりで。