'Rails has_many through has_and_belongs_to_many

I am trying to find way to get data from a has_and_belongs_to_many association through a secondary model. I'll say sorry now as I might not explain this right, so best I just show the associations and what I need to do. I am using Rails 5.

I have:

Incident Model:

incident has_and_belongs_to_many :apps

Apps Model:

app has_and_belongs_to_many :incidents

app belongs_to :service

Service Model:

has_many :apps

What I want to find is for my given service what Incidents its been involved in through the apps that it has, but I only want the unique Incidents.

Is there some way i can do @service.apps_incidents.unique and get a list of the unique incidents.

My migrations look like this:

Service Table:

class CreateServices < ActiveRecord::Migration[5.1]
  def change
    create_table :services do |t|
      t.string :name
      t.timestamps
    end
  end
end

Apps Table:

class CreateApps < ActiveRecord::Migration[5.1]
  def change
    create_table :apps do |t|
      t.string :name
      t.references :service, foreign_key: true
      t.timestamps
    end
  end
end

Incidents Table:

class CreateIncidents < ActiveRecord::Migration[5.1]
  def change
    create_table :incidents do |t|
      t.string :name
      t.timestamps
    end
  end
end

App/Incidents Join Table:

class CreateJoinTableAppsIncidents < ActiveRecord::Migration[5.1]
  def change
    create_join_table :apps, :incidents do |t|
      t.index [:incident_id, :app_id]
    end
  end
end


Solution 1:[1]

You can use uniq_by

class Service
  has_many :apps
  has_many :incidents, through: :apps
end

You can then do

@my_service.incidents.uniq_by(&:incident_id)

Solution 2:[2]

Add incidents to your Service

class Service
  has_many :apps
  has_many :incidents, through: :apps
end

Then

@service.incidents.uniq

OR

@service.incidents.distinct

This should do.

Solution 3:[3]

class Service
  has_many :apps
  has_many :incidents,  -> { distinct }, through: :apps
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SteveTurczyn
Solution 2 Sandip Mane
Solution 3 Sun Soul