Misha
Misha

Reputation: 1896

Rails create scope of duplicates records

If you need to pull all duplicates by name in the class you can achieve it by:

Company.select(:name).group(:name).having("count(*) > 1")

By what to do if you want it in the scope

scope :duplicates, -> { where (...?)}

Also in return I need few fields not only name. Did anyone had the same problem to create a scope?

Upvotes: 2

Views: 868

Answers (2)

Matouš Borák
Matouš Borák

Reputation: 15944

You need to run this in two queries. The first query selects the duplicate names, the second one selects the records with those duplicate names and uses the current_scope so that it can be chained with more scopes if needed (unfortunately current_scope seems to be a very useful but undocumented method):

scope :duplicates,
      -> {
        dup_names = Company.group(:name).having("count(*) > 1").pluck(:name)             
        current_scope.where(name: dup_names)
      }

(The dup_names variable will contain an array of duplicate names found among the companies.)

Then you can easily add further conditions on the duplicate records, for example:

Company.duplicates.where("name like 'a%'").limit(2)

will select just two companies with the name starting with 'a' (and with duplicate names).

Upvotes: 1

abookyun
abookyun

Reputation: 457

Since

scope :red, -> { where(color: 'red') }

is simply 'syntactic sugar' for defining an actual class method:

class Shirt < ActiveRecord::Base
  def self.red
    where(color: 'red')
  end
end

you could define scope like this:

scope :duplicates, -> { ids = select(:id).group(:name).having("count(name) > 1"); where(id: ids) }

Upvotes: 0

Related Questions