1

Given the following model structures;

class Project < ApplicationRecord
  has_many :leads
  has_and_belonds_to_many :clients
end

class Lead < ApplicationRecord
  belongs_to :project
end

class Client < ApplicationRecord
  has_and_belongs_to_many :projects
end

How you would suggest reporting on duplicate leads across a Client?

Right now I am doing something very gnarly with flattens and counts, it feels like there should be a 'Ruby way'.

Ideally I would like the interface to be able to say either Client.first.duplicate_leads or Lead.first.duplicate?.

Current (terrible) solution

@duplicate_leads = Client.all.map(&:duplicate_leads).flatten

Class Client
  def duplicate_leads
    leads = projects.includes(:leads).map(&:leads).flatten
    grouped_leads = leads.group_by(&:email)
    grouped_leads.select { |_, v| v.size > 1 }.map { |a| a[1][0] }.flatten
  end
end

Environment

  • Rails 5
  • Ruby 2.3.1
Toby
  • 8,483
  • 13
  • 45
  • 68
  • Cool solution here just fit to meet your needs! http://stackoverflow.com/questions/21669202/find-rows-with-multiple-duplicate-fields-with-active-record-rails-postgres – bkunzi01 Oct 12 '16 at 19:06
  • Thanks @bkunzi01 but that is for multiple columns in one table, not across multiple tables. – Toby Oct 12 '16 at 19:22

2 Answers2

1

You could try this.

class Client < ApplicationRecord
  has_and_belongs_to_many :projects
  has_many :leads, through: :projects

  def duplicate_leads
    duplicate_ids = leads.group(:email).having("count(email) > 1").count.keys
    Lead.where(id: duplicate_ids)
  end
end
Hass
  • 1,628
  • 1
  • 18
  • 31
0

You could try creating a has_many association from Lead through Project back to Lead, in which you use a lambda to dynamically join based on a match on email between the two records, and on the id not matching. This would mark both records as a duplicate -- if you wanted to mark only one then you can require that the id of one is less than the id of the other.

Some hints: Rails has_many with dynamic conditions

Community
  • 1
  • 1
David Aldridge
  • 51,479
  • 8
  • 68
  • 96