find_duplicates 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6418b13e2f8b0ef1e2560ecfd8a539c5f949a92a
4
- data.tar.gz: 86207fd75fbc54eb803627a6ce7884e32fb83156
3
+ metadata.gz: dcba9dbaac1d95a2a7db55acc525fe99044c7b15
4
+ data.tar.gz: 2bb1b972fbb79fbca75928e47c2e528fe1340eea
5
5
  SHA512:
6
- metadata.gz: 99d2919631fed769b0d0964212c6ad610b0d09745e0eb787c74745cb80972d47bfc47fed62636bba2473f92b1b969d8ee52e9a715b7e4e9d118a51465400911d
7
- data.tar.gz: 65309b95e0acb4da772c7aa992b702c3f1485ab157d1c3cea56f97f6acfa4f788f0fe5471f83eb1d8fd43a0a3bf20e569aa8b6e84ca67ce21a40445220699edf
6
+ metadata.gz: 4fc54d866ece1ca1602f08332fe841da89227f42abbf05aba28eece7728a28915075a69c6275c3e5d40a8a111bf3e181ddd9254feb795490cd190832f03c67ce
7
+ data.tar.gz: 487b12b8a2ff9a503352f230613049c1b4d3cadddd0d3237aeeb7b1382ad345afd7e400263bc4c0d6fdad7a4badba7a2d5e1fb5c94975c621a32f2da9bc04c7f
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # FindDuplicates
2
2
 
3
- This is home to the find_duplicates GEM.
4
-
5
- Use it to add methods to ActiveRecord models, that allow to find rows with duplicate values in certain columns. For example, find all users with the same first name, or find all items with the same price as a specific item.
3
+ This GEM allows you to find duplicate models with same value for a column, e.g.:
4
+ Find all users with the same first name.
6
5
 
7
6
  Just add 'find_duplicates' to your Gemfile, and you automatically enhance your AR models functionality.
8
7
 
@@ -39,6 +38,14 @@ class methods:
39
38
  > User.duplicates(:last_name) # => [@user1, @user2]
40
39
  ```
41
40
 
41
+ also works with multiple fields:
42
+ ```ruby
43
+ > @user4 = User.create first_name: 'John', last_name: 'Major'
44
+ > @user5 = User.create first_name: 'John', last_name: 'Major'
45
+ > User.duplicates(:first_name, :last_name) # => [@user4, @user5]
46
+ > User.duplicates([:first_name, :last_name]) # => [@user4, @user5]
47
+ ```
48
+
42
49
  instance methods:
43
50
  ```ruby
44
51
  > @user1.duplicate?(:first_name) # => true
@@ -46,6 +53,12 @@ instance methods:
46
53
  > @user1.duplicates_with_self(:last_name) # => [@user1, @user2]
47
54
  ```
48
55
 
56
+ instance methods also work with multiple fields:
57
+ ```ruby
58
+ > @user1.duplicates_with_self(:first_name, :last_name) # => []
59
+ > @user4.duplicates_with_self(:first_name, :last_name) # => [@user4, @user5]
60
+ ```
61
+
49
62
  ## Contributing
50
63
 
51
64
  1. Fork it
@@ -1,3 +1,3 @@
1
1
  module FindDuplicates
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -4,23 +4,48 @@ require 'active_support/concern'
4
4
 
5
5
  module FindDuplicates
6
6
  extend ActiveSupport::Concern
7
- def duplicate?(field)
8
- duplicates_with_self(field).count > 1
7
+ def duplicate?(*args)
8
+ set_fields(args)
9
+ duplicates_with_self(@fields).count > 1
9
10
  end
10
11
 
11
- def duplicates(field)
12
- duplicates_with_self(field).where('id <> ?', id)
12
+ def duplicates(*args)
13
+ set_fields(args)
14
+ duplicates_with_self(@fields).where('id <> ?', id)
13
15
  end
14
16
 
15
- def duplicates_with_self(field)
16
- self.class.where(field => self[field])
17
+ def duplicates_with_self(*args)
18
+ set_fields(args)
19
+ self.class.where(self.attributes.slice(*@fields))
17
20
  end
18
21
  module ClassMethods
19
- def duplicates(field)
20
- field = field.to_sym
21
- where field => self.select(['count(*)', field]).group(field).having('count(*) > 1').map(&field)
22
+ def duplicates(*args)
23
+ set_fields(args)
24
+ self.joins("join (
25
+ select #{fields_str}, count(*) as qty
26
+ from #{self.table_name}
27
+ group by #{fields_str}
28
+ having count(*) > 1
29
+ ) t on #{fields_query}").all
22
30
  end
31
+ private
32
+ def set_fields(args)
33
+ @fields = args.is_a?(Array) ? args : [args]
34
+ @fields = @fields.flatten.map &:to_s
35
+ end
36
+ def fields_str
37
+ @fields.join(',')
38
+ end
39
+ def fields_query
40
+ @fields.map {|f| "#{self.table_name}.#{f} = t.#{f}"}.join(' and ')
41
+ end
23
42
  end
43
+
44
+ private
45
+ def set_fields(args)
46
+ @fields = args.is_a?(Array) ? args : [args]
47
+ @fields = @fields.flatten.map &:to_s
48
+ end
24
49
  end
25
50
 
26
51
  class ActiveRecord::Base
@@ -5,43 +5,104 @@ describe FindDuplicates do
5
5
  setup
6
6
  end
7
7
 
8
- context 'duplicate records' do
9
- before do
10
- @first = TestDuplicates.create!(title: 'first!')
11
- @second = TestDuplicates.create!(title: 'second!')
12
- @third = TestDuplicates.create!(title: 'first!')
13
- end
8
+ context 'single' do
9
+ context 'duplicate records' do
10
+ before do
11
+ @first = TestDuplicates.create!(title: 'first!')
12
+ @second = TestDuplicates.create!(title: 'second!')
13
+ @third = TestDuplicates.create!(title: 'first!')
14
+ end
14
15
 
15
- it 'class duplicates' do
16
- expect(TestDuplicates.duplicates(:title)).not_to be_empty
17
- end
18
- it 'instance duplicates' do
19
- expect(@first.duplicates(:title)).to match_array([@third])
20
- end
21
- it 'duplicates_with_self' do
22
- expect(@first.duplicates_with_self(:title)).to match_array([@first, @third])
16
+ it 'class duplicates' do
17
+ expect(TestDuplicates.duplicates(:title)).to match_array([@first, @third])
18
+ end
19
+ it 'instance duplicates' do
20
+ expect(@first.duplicates(:title)).to match_array([@third])
21
+ end
22
+ it 'duplicates_with_self' do
23
+ expect(@first.duplicates_with_self(:title)).to match_array([@first, @third])
24
+ end
25
+ it 'duplicate?' do
26
+ expect(@first.duplicate?(:title)).to be_truthy
27
+ end
23
28
  end
24
- it 'duplicate?' do
25
- expect(@first.duplicate?(:title)).to be_truthy
29
+ context 'no duplicate records' do
30
+ before do
31
+ @first = TestDuplicates.create!(title: 'first!')
32
+ @second = TestDuplicates.create!(title: 'second!')
33
+ @third = TestDuplicates.create!(title: 'third!')
34
+ end
35
+ it 'duplicates' do
36
+ expect(TestDuplicates.duplicates(:title)).to be_empty
37
+ end
38
+ it 'instance duplicates' do
39
+ expect(@first.duplicates(:title)).to be_empty
40
+ end
41
+ it 'duplicates_with_self' do
42
+ expect(@first.duplicates_with_self(:title)).to match_array([@first])
43
+ end
44
+ it 'duplicate?' do
45
+ expect(@first.duplicate?(:title)).to be_falsey
46
+ end
26
47
  end
27
48
  end
28
- context 'no duplicate records' do
29
- before do
30
- @first = TestDuplicates.create!(title: 'first!')
31
- @second = TestDuplicates.create!(title: 'second!')
32
- @third = TestDuplicates.create!(title: 'third!')
49
+ context 'multiple' do
50
+ context 'duplicate records' do
51
+ before do
52
+ @first = TestDuplicatesMultiple.create!(first_name: 'first!', last_name: 'first!')
53
+ @second = TestDuplicatesMultiple.create!(first_name: 'first!', last_name: 'first!')
54
+ @third = TestDuplicatesMultiple.create!(first_name: 'second!', last_name: 'first!')
55
+ @forth = TestDuplicatesMultiple.create!(first_name: 'first!', last_name: 'second!')
56
+ end
57
+
58
+ it 'class duplicates' do
59
+ expect(TestDuplicatesMultiple.duplicates(:first_name, :last_name)).to match_array([@first, @second])
60
+ end
61
+ it 'instance duplicates' do
62
+ expect(@first.duplicates(:first_name, :last_name)).to match_array([@second])
63
+ end
64
+ it 'duplicates_with_self' do
65
+ expect(@first.duplicates_with_self(:first_name, :last_name)).to match_array([@first, @second])
66
+ end
67
+ it 'duplicate?' do
68
+ expect(@first.duplicate?(:first_name, :last_name)).to be_truthy
69
+ end
33
70
  end
34
- it 'duplicates' do
35
- expect(TestDuplicates.duplicates(:title)).to be_empty
71
+ context 'no duplicate records' do
72
+ before do
73
+ @first = TestDuplicatesMultiple.create!(first_name: 'first!', last_name: 'first!')
74
+ @second = TestDuplicatesMultiple.create!(first_name: 'first!', last_name: 'second!')
75
+ @third = TestDuplicatesMultiple.create!(first_name: 'second!', last_name: 'first!')
76
+ end
77
+ it 'duplicates' do
78
+ expect(TestDuplicatesMultiple.duplicates(:first_name, :last_name)).to be_empty
79
+ end
80
+ it 'instance duplicates' do
81
+ expect(@first.duplicates(:first_name, :last_name)).to be_empty
82
+ end
83
+ it 'duplicates_with_self' do
84
+ expect(@first.duplicates_with_self(:first_name, :last_name)).to match_array([@first])
85
+ end
86
+ it 'duplicate?' do
87
+ expect(@first.duplicate?(:first_name, :last_name)).to be_falsey
88
+ end
36
89
  end
37
- it 'instance duplicates' do
38
- expect(@first.duplicates(:title)).to be_empty
90
+ end
91
+ context 'params' do
92
+ it 'single param' do
93
+ td = TestDuplicatesMultiple.new
94
+ td.send(:set_fields, [:first_name])
95
+ expect(td.instance_variable_get(:@fields)).to eql(['first_name'])
39
96
  end
40
- it 'duplicates_with_self' do
41
- expect(@first.duplicates_with_self(:title)).to match_array([@first])
97
+ it 'multiple params' do
98
+ td = TestDuplicatesMultiple.new
99
+ td.send(:set_fields, [:first_name, :last_name])
100
+ expect(td.instance_variable_get(:@fields)).to eql(['first_name', 'last_name'])
42
101
  end
43
- it 'duplicate?' do
44
- expect(@first.duplicate?(:title)).to be_falsey
102
+ it 'params array' do
103
+ td = TestDuplicatesMultiple.new
104
+ td.send(:set_fields, [[:first_name, :last_name]])
105
+ expect(td.instance_variable_get(:@fields)).to eql(['first_name', 'last_name'])
45
106
  end
46
107
  end
47
108
  end
data/spec/spec_helper.rb CHANGED
@@ -28,7 +28,15 @@ def setup
28
28
  t.column :title, :string
29
29
  end
30
30
  end
31
+ ActiveRecord::Schema.define do
32
+ create_table :test_duplicates_multiples, force: true do |t|
33
+ t.column :first_name, :string
34
+ t.column :last_name, :string
35
+ end
36
+ end
31
37
  end
32
38
 
33
39
  class TestDuplicates < ActiveRecord::Base
34
40
  end
41
+ class TestDuplicatesMultiple < ActiveRecord::Base
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: find_duplicates
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - adam klein
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-02 00:00:00.000000000 Z
12
+ date: 2014-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord