dedupe 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,11 @@
1
+ # .document is used by rdoc and yard to know how to generate documentation
2
+ # for example, it can be used to control how rdoc gets built when you do `gem install foo`
3
+
4
+ README.rdoc
5
+ lib/**/*.rb
6
+ bin/*
7
+
8
+ # Files below this - are treated as 'extra files', and aren't parsed for ruby code
9
+ -
10
+ features/**/*.feature
11
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
data/.rvmrc ADDED
@@ -0,0 +1,5 @@
1
+ # default gemset
2
+ rvm 1.9.2@dedupe
3
+
4
+ # return to system ruby on leaving directory
5
+ rvm_project_rvmrc_default=1
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "activesupport", "~> 3.0.0"
4
+ gem "activemodel", "~> 3.0.0"
5
+
6
+ group :development do
7
+ gem "rspec", ">= 2.0.0.beta.19"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.5.0.pre3"
10
+ gem "rcov", ">= 0"
11
+ gem "mongoid", "2.0.0.beta.19"
12
+ gem "bson_ext", "1.0.9"
13
+ gem "activerecord", "~> 3.0.0"
14
+ gem "sqlite3-ruby", "~> 1.3.1"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,62 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.0)
5
+ activesupport (= 3.0.0)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4.1)
8
+ activerecord (3.0.0)
9
+ activemodel (= 3.0.0)
10
+ activesupport (= 3.0.0)
11
+ arel (~> 1.0.0)
12
+ tzinfo (~> 0.3.23)
13
+ activesupport (3.0.0)
14
+ arel (1.0.1)
15
+ activesupport (~> 3.0.0)
16
+ bson (1.0.9)
17
+ bson_ext (1.0.9)
18
+ builder (2.1.2)
19
+ diff-lcs (1.1.2)
20
+ git (1.2.5)
21
+ i18n (0.4.1)
22
+ jeweler (1.5.0.pre3)
23
+ bundler (~> 1.0.0)
24
+ git (>= 1.2.5)
25
+ rake
26
+ mongo (1.0.9)
27
+ bson (>= 1.0.5)
28
+ mongoid (2.0.0.beta.19)
29
+ activemodel (~> 3.0)
30
+ mongo (= 1.0.9)
31
+ tzinfo (~> 0.3.22)
32
+ will_paginate (~> 3.0.pre)
33
+ rake (0.8.7)
34
+ rcov (0.9.9)
35
+ rspec (2.0.0.beta.22)
36
+ rspec-core (= 2.0.0.beta.22)
37
+ rspec-expectations (= 2.0.0.beta.22)
38
+ rspec-mocks (= 2.0.0.beta.22)
39
+ rspec-core (2.0.0.beta.22)
40
+ rspec-expectations (2.0.0.beta.22)
41
+ diff-lcs (>= 1.1.2)
42
+ rspec-mocks (2.0.0.beta.22)
43
+ rspec-core (= 2.0.0.beta.22)
44
+ rspec-expectations (= 2.0.0.beta.22)
45
+ sqlite3-ruby (1.3.1)
46
+ tzinfo (0.3.23)
47
+ will_paginate (3.0.pre2)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ activemodel (~> 3.0.0)
54
+ activerecord (~> 3.0.0)
55
+ activesupport (~> 3.0.0)
56
+ bson_ext (= 1.0.9)
57
+ bundler (~> 1.0.0)
58
+ jeweler (~> 1.5.0.pre3)
59
+ mongoid (= 2.0.0.beta.19)
60
+ rcov
61
+ rspec (>= 2.0.0.beta.19)
62
+ sqlite3-ruby (~> 1.3.1)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Brent Hargrave
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,85 @@
1
+ = dedupe
2
+
3
+
4
+ == Description
5
+
6
+ Dedupe provides Mongoid and ActiveRecord 3 with a uniqueness validation that protects your datastore from duplicate records, defined by your domain.
7
+
8
+ The following model defines a uniqueness constraint:
9
+
10
+ class Model
11
+ include Mongoid::Document
12
+
13
+ field :foo
14
+ field :bar
15
+ field :baz
16
+
17
+ validates_uniqueness :using => :with_matching_foo_and_bar
18
+ scope :with_matching_foo_and_bar, lambda { |instance|
19
+ where :foo => instance.foo, :bar => instance.bar
20
+ # our hypothetical domain requires that we disregard :baz
21
+ }
22
+
23
+ end
24
+
25
+ Any attempt to save a record with the same "foo" and "bar" values will fail.
26
+
27
+ > existing = Model.create! :foo => "a", :bar => "b", :baz => "c"
28
+ => #<Model _id: 123abc, foo: "a", bar: "b", baz: "c">
29
+
30
+ > duplicate = Model.new :foo => "a", :bar => "b", :baz => "z"
31
+ => #<Model _id: 456def, foo: "a", bar: "b", baz: "z">
32
+
33
+ > duplicate.valid?
34
+ => false
35
+
36
+ > duplicate.errors.full_messages
37
+ => ["Duplicates existing record"]
38
+
39
+ > duplicate.save!
40
+ Mongoid::Errors::Validations: Validation failed...
41
+
42
+ The gem also provides a few other methods, possibly useful for cleaning up datastores already corrupted with duplicate records.
43
+
44
+ > duplicate.duplicate?
45
+ => true
46
+
47
+ > duplicate.duplicates.to_a
48
+ => [#<Model _id: 123abc, foo: "a", bar: "b", baz: "c">]
49
+
50
+ > existing.duplicates.to_a
51
+ => []
52
+
53
+
54
+ == Installation & Usage
55
+
56
+ Add the gem to your Gemfile:
57
+ gem 'dedupe'
58
+
59
+ Add a scope or "finder" method to your model that a) accepts an instance of your model and b) returns a relation/criterion that would select all duplicate instances in your datastore. In the above example, this method is:
60
+ scope :with_matching_foo_and_bar, lambda { |instance|
61
+ where :foo => instance.foo, :baz => instance.baz
62
+ }
63
+
64
+ But you could also define:
65
+ def with_matching_foo_and_bar(instance)
66
+ where :foo => instance.foo, :baz => instance.baz
67
+ end
68
+
69
+ Then, mix the Dedupe module into your model using the "validates_uniqueness" macro, passing it the name of your scope/finder:
70
+ validates_uniqueness :using => :with_matching_foo_and_bar
71
+
72
+
73
+ == Note on Patches/Pull Requests
74
+
75
+ * Fork the project.
76
+ * Make your feature addition or bug fix.
77
+ * Add tests for it. This is important so I don't break it in a
78
+ future version unintentionally.
79
+ * Commit, do not mess with rakefile, version, or history.
80
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
81
+ * Send me a pull request. Bonus points for topic branches.
82
+
83
+ == Copyright
84
+
85
+ Copyright (c) 2010 Brent Hargrave. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "dedupe"
16
+ gem.summary = %Q{ActiveModel validation against duplicating records.}
17
+ gem.description = %Q{ActiveModel validation against duplicating records.}
18
+ gem.email = "brent.hargrave@gmail.com"
19
+ gem.homepage = "http://github.com/jamescallmebrent/dedupe"
20
+ gem.authors = ["Brent Hargrave"]
21
+ end
22
+ Jeweler::RubygemsDotOrgTasks.new
23
+
24
+ require 'rspec/core'
25
+ require 'rspec/core/rake_task'
26
+ RSpec::Core::RakeTask.new(:spec) do |spec|
27
+ spec.pattern = FileList['spec/**/*_spec.rb']
28
+ end
29
+
30
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
31
+ spec.pattern = 'spec/**/*_spec.rb'
32
+ spec.rcov = true
33
+ end
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "dedupe #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/lib/dedupe.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'dedupe/errors'
2
+ require 'dedupe/validations'
3
+ require 'dedupe/orm/mongoid'
4
+ require 'dedupe/orm/active_record'
5
+
6
+ module Dedupe
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ cattr_accessor :dedupe_scope_name
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def validates_uniqueness(options={})
16
+ self.dedupe_scope_name = options.delete :using
17
+ if defined?(Mongoid::Document) && self.new.is_a?(Mongoid::Document)
18
+ self.send :include, Orm::Mongoid
19
+ elsif defined?(ActiveRecord::Base) && self.new.is_a?(ActiveRecord::Base)
20
+ self.send :include, Orm::ActiveRecord
21
+ end
22
+ self.send :include, Validations
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ Mongoid::Document.send :include, Dedupe if defined? Mongoid::Document
30
+ ActiveRecord::Base.send :include, Dedupe if defined? ActiveRecord::Base
@@ -0,0 +1,6 @@
1
+ module Dedupe
2
+ module Errors
3
+ class MissingScope < StandardError; end
4
+ class InvalidScope < StandardError; end
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ module Dedupe
2
+ module Orm
3
+ module ActiveRecord
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ scope :excluding, lambda { |instance|
8
+ where('id <> ?', instance.id.to_i)
9
+ }
10
+ end
11
+
12
+ module InstanceMethods
13
+ include Errors
14
+
15
+ def duplicates
16
+ klass, scope_name = self.class, self.class.dedupe_scope_name
17
+ raise MissingScope unless klass.respond_to? scope_name
18
+ result_set = klass.send scope_name, self
19
+ raise InvalidScope unless result_set.is_a? ::ActiveRecord::Relation
20
+ result_set.excluding self
21
+ end
22
+
23
+ def duplicate?
24
+ self.duplicates.present?
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ module Dedupe
2
+ module Orm
3
+ module Mongoid
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ scope :excluding, lambda { |instance|
8
+ excludes(:id => instance.id)
9
+ }
10
+ end
11
+
12
+ module InstanceMethods
13
+ include Errors
14
+
15
+ def duplicates
16
+ klass, scope_name = self.class, self.class.dedupe_scope_name
17
+ raise MissingScope unless klass.respond_to? scope_name
18
+ result_set = klass.send scope_name, self
19
+ raise InvalidScope unless result_set.is_a? ::Mongoid::Criteria
20
+ result_set.excluding self
21
+ end
22
+
23
+ def duplicate?
24
+ self.duplicates.present?
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module Dedupe
2
+ module Validations
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validates_with RecordUniquenessValidator
7
+ end
8
+
9
+ class RecordUniquenessValidator < ActiveModel::Validator
10
+ def validate(record)
11
+ if record.duplicate?
12
+ record.errors.add :base, "Duplicates existing record"
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,148 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ shared_examples_for "any Dedupe helper method" do
4
+ it "should raise error if validates_uniqueness omitted" do
5
+ instance ||= @macroless_model.new
6
+ lambda do
7
+ instance.send(@method_name)
8
+ end.should raise_error(NoMethodError)
9
+ end
10
+ end
11
+ shared_examples_for "any Dedupe instance method" do
12
+ it "should raise error if scope omitted" do
13
+ instance = @scopeless_model.new
14
+ lambda do
15
+ instance.send(@method_name)
16
+ end.should raise_error(Dedupe::Errors::MissingScope)
17
+ end
18
+ it "should raise error if scope returns a non-criterion" do
19
+ instance = @invalid_scope_model.new
20
+ lambda do
21
+ instance.send(@method_name)
22
+ end.should raise_error(Dedupe::Errors::InvalidScope)
23
+ end
24
+ end
25
+
26
+ shared_examples_for "any supported ORM" do
27
+ context "finding" do
28
+ context "all but a provided instance (excluding)" do
29
+ before do
30
+ @existing = @model.create!(:foo => 'a', :bar => 'b')
31
+ @others = []
32
+ @others << @model.create!(:foo => 'd', :bar => 'e')
33
+ @others << @model.create!(:foo => 'g', :bar => 'g')
34
+ @found = @model.excluding(@existing).to_a
35
+ end
36
+ it "should not include that instance" do
37
+ @found.should_not include(@existing)
38
+ end
39
+ it "should include all other instances" do
40
+ @others.all? { |instance| @found.include?(instance) }.should be_true
41
+ end
42
+ it "should raise error if validates_uniqueness omitted" do
43
+ lambda do
44
+ @macroless_model.excluding
45
+ end.should raise_error(NoMethodError)
46
+ end
47
+ end
48
+ context 'duplicates of a provided instance (dev-defined scope/finder)' do
49
+ before do
50
+ @existing = @model.create! :foo => 'foo', :bar => 'bar'
51
+ @unique_bar = @model.create! :foo => 'foo', :bar => 'unique'
52
+ @unique_foo = @model.create! :foo => 'unique', :bar => 'bar'
53
+ @duplicate = @model.new :foo => 'foo', :bar => 'bar'
54
+ @found = @model.with_attributes_of(@duplicate).to_a
55
+ end
56
+ it 'should exclude instances with only *some* duplicate attributes' do
57
+ @found.should_not include(@unique_foo)
58
+ @found.should_not include(@unique_bar)
59
+ end
60
+ it 'should include instances with duplicate attributes' do
61
+ @found.should include(@existing)
62
+ end
63
+ end
64
+ end
65
+ context "instance" do
66
+ context "duplicates" do
67
+ before do
68
+ @method_name = "duplicates"
69
+ @existing = @model.create! :foo => 'a', :bar => 'b'
70
+ @other = @model.create! :foo => 'c', :bar => 'd'
71
+ @proposed = @model.new :foo => 'a', :bar => 'b'
72
+ end
73
+ it "should include its duplicate" do
74
+ @proposed.duplicates.should include(@existing)
75
+ end
76
+ it "should exclude non-duplicates" do
77
+ @proposed.duplicates.should_not include(@other)
78
+ end
79
+ it "should exclude itself" do
80
+ @existing.duplicates.should_not include(@existing)
81
+ end
82
+ it_should_behave_like "any Dedupe helper method"
83
+ it_should_behave_like "any Dedupe instance method"
84
+ end
85
+ context "duplicate?" do
86
+ before do
87
+ @method_name = "duplicate?"
88
+ @existing = @model.create! :foo => 'a', :bar => 'b'
89
+ @duplicate = @model.new :foo => 'a', :bar => 'b'
90
+ @non_duplicate = @model.new :foo => 'c', :bar => 'd'
91
+ end
92
+ it "duplicate? should be true if it has duplicates" do
93
+ @duplicate.should be_duplicate
94
+ end
95
+ it "duplicate? should be false if it lacks duplicates" do
96
+ @non_duplicate.should_not be_duplicate
97
+ end
98
+ # shared behavior?
99
+ it_should_behave_like "any Dedupe helper method"
100
+ it_should_behave_like "any Dedupe instance method"
101
+ end
102
+ context "validation (valid?)" do
103
+ before do
104
+ @method_name = "valid?"
105
+ @existing = @model.create! :foo => 'a', :bar => 'b'
106
+ @duplicate = @model.new :foo => 'a', :bar => 'b'
107
+ @non_duplicate = @model.new :foo => 'c', :bar => 'd'
108
+ end
109
+ it "with unique attributes should be true" do
110
+ @non_duplicate.should be_valid
111
+ end
112
+ context "with duplicate attributes" do
113
+ it "should be false" do
114
+ @duplicate.should_not be_valid
115
+ end
116
+ it "should add an error" do
117
+ @duplicate.valid? # call valid
118
+ @duplicate.errors[:base].should include "Duplicates existing record"
119
+ end
120
+ end
121
+ it_should_behave_like "any Dedupe instance method"
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "Mongoid model" do
127
+ before do
128
+ @macroless_model = MongoidMacrolessModel
129
+ @scopeless_model = MongoidScopelessModel
130
+ @invalid_scope_model = MongoidInvalidScopeModel
131
+ @model = MongoidModel
132
+ end
133
+ it_should_behave_like "any supported ORM"
134
+ end
135
+
136
+ describe "ActiveRecord model" do
137
+ before do
138
+ @macroless_model = ActiveRecordMacrolessModel
139
+ @macroless_model.destroy_all
140
+ @scopeless_model = ActiveRecordScopelessModel
141
+ @scopeless_model.destroy_all
142
+ @invalid_scope_model = ActiveRecordInvalidScopeModel
143
+ @invalid_scope_model.destroy_all
144
+ @model = ActiveRecordModel
145
+ @model.destroy_all
146
+ end
147
+ it_should_behave_like "any supported ORM"
148
+ end
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+
12
+ require "mongoid"
13
+ require "active_record"
14
+ require "dedupe"
15
+ require "rspec"
16
+
17
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |file| require file }
@@ -0,0 +1,35 @@
1
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3',
2
+ :database => ':memory:'
3
+ ActiveRecord::Migration.verbose = false
4
+ tables = %w{ active_record_macroless_models active_record_scopeless_models active_record_invalid_scope_models active_record_models }
5
+ ActiveRecord::Schema.define(:version => 1) do
6
+ tables.each do |table_name|
7
+ create_table table_name.intern, :force => true do |t|
8
+ t.datetime :created_at
9
+ t.datetime :updated_at
10
+ t.string :foo
11
+ t.string :bar
12
+ end
13
+ end
14
+ end
15
+
16
+ # a "vanilla" ActiveRecord model
17
+ class ActiveRecordMacrolessModel < ActiveRecord::Base
18
+ end
19
+ # ActiveRecord model with macro included, but required scope "forgotten"
20
+ class ActiveRecordScopelessModel < ActiveRecordMacrolessModel
21
+ validates_uniqueness :using => :with_attributes_of
22
+ end
23
+ # ActiveRecord model with gem improperly implemented
24
+ # returns an instance of Array instead of Criteria
25
+ class ActiveRecordInvalidScopeModel < ActiveRecordScopelessModel
26
+ def self.with_attributes_of(instance)
27
+ where(:foo => instance.foo, :bar => instance.bar).to_a
28
+ end
29
+ end
30
+ # ActiveRecord model with gem properly implemented
31
+ class ActiveRecordModel < ActiveRecordScopelessModel
32
+ def self.with_attributes_of(instance)
33
+ where(:foo => instance.foo, :bar => instance.bar)
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ Mongoid.configure do |config|
2
+ name = "mongoid_test"
3
+ host = "localhost"
4
+ config.master = Mongo::Connection.new.db(name)
5
+ config.logger = nil
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.before do
10
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
11
+ end
12
+ end
13
+
14
+ # a "vanilla" Mongoid model
15
+ class MongoidMacrolessModel
16
+ include Mongoid::Document
17
+ field :foo
18
+ field :bar
19
+ field :baz
20
+ end
21
+
22
+ # a Mongoid model with macro included, but required scope "forgotten"
23
+ class MongoidScopelessModel < MongoidMacrolessModel
24
+ validates_uniqueness :using => :with_attributes_of
25
+ end
26
+
27
+ # a Mongoid model with gem improperly implemented
28
+ # returns an instance of Array instead of Criteria
29
+ class MongoidInvalidScopeModel < MongoidScopelessModel
30
+ def self.with_attributes_of(instance)
31
+ where(:foo => instance.foo, :bar => instance.bar).to_a
32
+ end
33
+ end
34
+
35
+ # a Mongoid model with gem properly implemented
36
+ class MongoidModel < MongoidScopelessModel
37
+ def self.with_attributes_of(instance)
38
+ where(:foo => instance.foo, :bar => instance.bar)
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,239 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dedupe
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Brent Hargrave
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-02 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 3
29
+ - 0
30
+ - 0
31
+ version: 3.0.0
32
+ type: :runtime
33
+ prerelease: false
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: activemodel
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 3
44
+ - 0
45
+ - 0
46
+ version: 3.0.0
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 2
59
+ - 0
60
+ - 0
61
+ - beta
62
+ - 19
63
+ version: 2.0.0.beta.19
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: bundler
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 1
76
+ - 0
77
+ - 0
78
+ version: 1.0.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ name: jeweler
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ segments:
90
+ - 1
91
+ - 5
92
+ - 0
93
+ - pre3
94
+ version: 1.5.0.pre3
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: *id005
98
+ - !ruby/object:Gem::Dependency
99
+ name: rcov
100
+ requirement: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: *id006
111
+ - !ruby/object:Gem::Dependency
112
+ name: mongoid
113
+ requirement: &id007 !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - "="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 2
120
+ - 0
121
+ - 0
122
+ - beta
123
+ - 19
124
+ version: 2.0.0.beta.19
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: *id007
128
+ - !ruby/object:Gem::Dependency
129
+ name: bson_ext
130
+ requirement: &id008 !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - "="
134
+ - !ruby/object:Gem::Version
135
+ segments:
136
+ - 1
137
+ - 0
138
+ - 9
139
+ version: 1.0.9
140
+ type: :development
141
+ prerelease: false
142
+ version_requirements: *id008
143
+ - !ruby/object:Gem::Dependency
144
+ name: activerecord
145
+ requirement: &id009 !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ segments:
151
+ - 3
152
+ - 0
153
+ - 0
154
+ version: 3.0.0
155
+ type: :development
156
+ prerelease: false
157
+ version_requirements: *id009
158
+ - !ruby/object:Gem::Dependency
159
+ name: sqlite3-ruby
160
+ requirement: &id010 !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ~>
164
+ - !ruby/object:Gem::Version
165
+ segments:
166
+ - 1
167
+ - 3
168
+ - 1
169
+ version: 1.3.1
170
+ type: :development
171
+ prerelease: false
172
+ version_requirements: *id010
173
+ description: ActiveModel validation against duplicating records.
174
+ email: brent.hargrave@gmail.com
175
+ executables: []
176
+
177
+ extensions: []
178
+
179
+ extra_rdoc_files:
180
+ - LICENSE
181
+ - README.rdoc
182
+ files:
183
+ - .document
184
+ - .gitignore
185
+ - .rspec
186
+ - .rvmrc
187
+ - Gemfile
188
+ - Gemfile.lock
189
+ - LICENSE
190
+ - README.rdoc
191
+ - Rakefile
192
+ - VERSION
193
+ - lib/dedupe.rb
194
+ - lib/dedupe/errors.rb
195
+ - lib/dedupe/orm/active_record.rb
196
+ - lib/dedupe/orm/mongoid.rb
197
+ - lib/dedupe/validations.rb
198
+ - spec/dedupe_spec.rb
199
+ - spec/spec_helper.rb
200
+ - spec/support/active_record.rb
201
+ - spec/support/mongoid.rb
202
+ has_rdoc: true
203
+ homepage: http://github.com/jamescallmebrent/dedupe
204
+ licenses: []
205
+
206
+ post_install_message:
207
+ rdoc_options: []
208
+
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ hash: -1388205667040375508
217
+ segments:
218
+ - 0
219
+ version: "0"
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ none: false
222
+ requirements:
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ segments:
226
+ - 0
227
+ version: "0"
228
+ requirements: []
229
+
230
+ rubyforge_project:
231
+ rubygems_version: 1.3.7
232
+ signing_key:
233
+ specification_version: 3
234
+ summary: ActiveModel validation against duplicating records.
235
+ test_files:
236
+ - spec/dedupe_spec.rb
237
+ - spec/spec_helper.rb
238
+ - spec/support/active_record.rb
239
+ - spec/support/mongoid.rb