is_unique 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "is_unique"
5
+ gemspec.summary = "ActiveRecord extension to prevent duplicate records"
6
+ gemspec.description = "Makes ActiveRecord return existing records instead of creating duplicates"
7
+ gemspec.email = "eugene.bolshakov@gmail.com"
8
+ gemspec.homepage = "http://github.com/loco2/is_unique"
9
+ gemspec.authors = ["Eugene Bolshakov"]
10
+ gemspec.add_dependency 'activerecord', '2.3.5'
11
+ end
12
+ Jeweler::GemcutterTasks.new
13
+ rescue LoadError
14
+ puts "Jeweler not available. Install it with: gem install jeweler"
15
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,16 @@
1
+ class IsUniqueGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'is_unique_migration.rb', 'db/migrate',
5
+ :assigns => {:unique_hash_column => actions.first || 'unique_hash' }
6
+ end
7
+ end
8
+
9
+ def banner
10
+ "Usage: #{$0} #{spec.name} ModelName [custom_unique_has_column_name] [options]"
11
+ end
12
+
13
+ def file_name
14
+ "add_unique_hash_column_to_#{@plural_name}"
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ class <%= file_name.camelcase %> < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :<%= table_name %>, :<%= unique_hash_column %>, :integer
4
+ add_index :<%= table_name %>, :<%= unique_hash_column %>
5
+ end
6
+
7
+ def self.down
8
+ remove_column :<%= table_name %>, :<%= unique_hash_column %>
9
+ end
10
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'lib', 'is_unique')
data/is_unique.gemspec ADDED
@@ -0,0 +1,51 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{is_unique}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Eugene Bolshakov"]
12
+ s.date = %q{2010-03-22}
13
+ s.description = %q{Makes ActiveRecord return existing records instead of creating duplicates}
14
+ s.email = %q{eugene.bolshakov@gmail.com}
15
+ s.files = [
16
+ "Rakefile",
17
+ "VERSION",
18
+ "generators/is_unique/is_unique_generator.rb",
19
+ "generators/is_unique/templates/is_unique_migration.rb",
20
+ "init.rb",
21
+ "is_unique.gemspec",
22
+ "lib/is_unique.rb",
23
+ "spec/spec_helper.rb",
24
+ "spec/support/db.rb",
25
+ "spec/unique_model_spec.rb"
26
+ ]
27
+ s.homepage = %q{http://github.com/loco2/is_unique}
28
+ s.rdoc_options = ["--charset=UTF-8"]
29
+ s.require_paths = ["lib"]
30
+ s.rubygems_version = %q{1.3.6}
31
+ s.summary = %q{ActiveRecord extension to prevent duplicate records}
32
+ s.test_files = [
33
+ "spec/unique_model_spec.rb",
34
+ "spec/support/db.rb",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+
38
+ if s.respond_to? :specification_version then
39
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<activerecord>, ["= 2.3.5"])
44
+ else
45
+ s.add_dependency(%q<activerecord>, ["= 2.3.5"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<activerecord>, ["= 2.3.5"])
49
+ end
50
+ end
51
+
data/lib/is_unique.rb ADDED
@@ -0,0 +1,61 @@
1
+ module IsUnique
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ end
5
+
6
+ module ClassMethods
7
+ def is_unique(options = {})
8
+
9
+ write_inheritable_attribute :is_unique_hash_column, options[:hash_column] || 'unique_hash'
10
+ class_inheritable_reader :is_unique_hash_column
11
+
12
+ write_inheritable_attribute :is_unique_ignore, [
13
+ primary_key,
14
+ is_unique_hash_column.to_s,
15
+ 'created_at',
16
+ 'updated_at'
17
+ ].concat(Array(options[:ignore]).map(&:to_s))
18
+
19
+ self.class_eval do
20
+ include InstanceMethods
21
+
22
+ before_save :calculate_unique_hash
23
+ end
24
+ end
25
+ end
26
+
27
+ module InstanceMethods
28
+ private
29
+
30
+ def is_unique_hash
31
+ send(self.class.is_unique_hash_column)
32
+ end
33
+
34
+ def is_unique_hash=(value)
35
+ send("#{self.class.is_unique_hash_column}=", value)
36
+ end
37
+
38
+ def create
39
+ if existing = self.class.find(:first, :conditions => {self.class.is_unique_hash_column => is_unique_hash})
40
+ self.id = existing.id
41
+ @new_record = false
42
+ reload
43
+ id
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ def calculate_unique_hash
50
+ self.is_unique_hash = unique_attributes.hash
51
+ end
52
+
53
+ def unique_attributes
54
+ attributes.except(*self.class.read_inheritable_attribute(:is_unique_ignore))
55
+ end
56
+ end
57
+ end
58
+
59
+ ActiveRecord::Base.class_eval do
60
+ include IsUnique
61
+ end
@@ -0,0 +1,5 @@
1
+ require 'active_record'
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/is_unique")
3
+ require 'spec'
4
+
5
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
@@ -0,0 +1,31 @@
1
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
2
+
3
+ def suppress_stdout
4
+ tmp = $stdout
5
+ $stdout = StringIO.new
6
+ yield
7
+ $stdout = tmp
8
+ end
9
+
10
+ def setup_db
11
+ ActiveRecord::Schema.define(:version => 1) do
12
+ create_table :locations do |t|
13
+ t.string :name
14
+ t.float :lat, :lng
15
+ t.string :alias
16
+ t.integer :unique_hash
17
+ t.timestamps
18
+ end
19
+ end
20
+ end
21
+
22
+ def teardown_db
23
+ ActiveRecord::Base.connection.tables.each do |table|
24
+ ActiveRecord::Base.connection.drop_table(table)
25
+ end
26
+ end
27
+
28
+ Spec::Runner.configure do |config|
29
+ config.before(:all) { suppress_stdout { setup_db } }
30
+ config.after(:all) { suppress_stdout { teardown_db } }
31
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ class Location < ActiveRecord::Base
4
+ # String name
5
+ # Float lat
6
+ # Float lng
7
+ # String alias
8
+ # Integer unique_hash
9
+
10
+ is_unique :ignore => :alias
11
+ end
12
+
13
+ describe "A unique model" do
14
+ before(:each) do
15
+ @it = Location.create(
16
+ :name => 'London',
17
+ :lat => '51.5084152563931',
18
+ :lng => '-0.125532746315002',
19
+ :alias => 'Londinium'
20
+ )
21
+ end
22
+
23
+ it "should not create a new record with the same attributes" do
24
+ new_record = @it.clone
25
+ lambda { new_record.save! }.
26
+ should_not change(Location, :count)
27
+ end
28
+
29
+ it "should not create a new record with a different ignored attribute" do
30
+ new_record = @it.clone
31
+ new_record.alias = 'Greater London'
32
+ lambda { new_record.save! }.
33
+ should_not change(Location, :count)
34
+ end
35
+
36
+ it "should return the existing record on creation" do
37
+ new_record = @it.clone
38
+ new_record.save!
39
+ new_record.should == @it
40
+ end
41
+
42
+ it "should allow to create a record with different attributes" do
43
+ new_record = @it.clone
44
+ new_record.name = 'Greater London'
45
+ lambda { new_record.save! }.
46
+ should change(Location, :count).by(1)
47
+ new_record.should_not == @it
48
+ end
49
+
50
+ it "should allow to create a record with original attributes when an existing record is updated" do
51
+ new_record = @it.clone
52
+ @it.update_attribute(:name, 'Greater London')
53
+ lambda { new_record.save! }.
54
+ should change(Location, :count).by(1)
55
+ new_record.should_not == @it
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: is_unique
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Eugene Bolshakov
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-22 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activerecord
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 5
31
+ version: 2.3.5
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: Makes ActiveRecord return existing records instead of creating duplicates
35
+ email: eugene.bolshakov@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - Rakefile
44
+ - VERSION
45
+ - generators/is_unique/is_unique_generator.rb
46
+ - generators/is_unique/templates/is_unique_migration.rb
47
+ - init.rb
48
+ - is_unique.gemspec
49
+ - lib/is_unique.rb
50
+ - spec/spec_helper.rb
51
+ - spec/support/db.rb
52
+ - spec/unique_model_spec.rb
53
+ has_rdoc: true
54
+ homepage: http://github.com/loco2/is_unique
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.6
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: ActiveRecord extension to prevent duplicate records
83
+ test_files:
84
+ - spec/unique_model_spec.rb
85
+ - spec/support/db.rb
86
+ - spec/spec_helper.rb