natural_key 0.2.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/CHANGELOG +8 -0
- data/Manifest +30 -0
- data/README.rdoc +52 -0
- data/Rakefile +15 -0
- data/VERSION.yml +4 -0
- data/lib/natural_key/base.rb +33 -0
- data/lib/natural_key.rb +9 -0
- data/natural_key.gemspec +31 -0
- data/pkg/natural_key-0.1.0/CHANGELOG +8 -0
- data/pkg/natural_key-0.1.0/Manifest +30 -0
- data/pkg/natural_key-0.1.0/README.rdoc +52 -0
- data/pkg/natural_key-0.1.0/Rakefile +15 -0
- data/pkg/natural_key-0.1.0/VERSION.yml +4 -0
- data/pkg/natural_key-0.1.0/lib/natural_key/base.rb +33 -0
- data/pkg/natural_key-0.1.0/lib/natural_key.rb +9 -0
- data/pkg/natural_key-0.1.0/natural_key.gemspec +32 -0
- data/pkg/natural_key-0.1.0/test/database.yml +23 -0
- data/pkg/natural_key-0.1.0/test/fixtures/schema.rb +9 -0
- data/pkg/natural_key-0.1.0/test/lib/activerecord_test_case.rb +34 -0
- data/pkg/natural_key-0.1.0/test/lib/activerecord_test_connector.rb +76 -0
- data/pkg/natural_key-0.1.0/test/test_helper.rb +14 -0
- data/pkg/natural_key-0.1.0/test/test_natural_key.rb +33 -0
- data/pkg/natural_key-0.1.0.gem +0 -0
- data/pkg/natural_key-0.1.0.tar.gz +0 -0
- data/test/database.yml +23 -0
- data/test/fixtures/schema.rb +9 -0
- data/test/lib/activerecord_test_case.rb +34 -0
- data/test/lib/activerecord_test_connector.rb +76 -0
- data/test/test_helper.rb +14 -0
- data/test/test_natural_key.rb +33 -0
- metadata +93 -0
data/CHANGELOG
ADDED
data/Manifest
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
VERSION.yml
|
6
|
+
lib/natural_key.rb
|
7
|
+
lib/natural_key/base.rb
|
8
|
+
natural_key.gemspec
|
9
|
+
pkg/natural_key-0.1.0.gem
|
10
|
+
pkg/natural_key-0.1.0.tar.gz
|
11
|
+
pkg/natural_key-0.1.0/CHANGELOG
|
12
|
+
pkg/natural_key-0.1.0/Manifest
|
13
|
+
pkg/natural_key-0.1.0/README.rdoc
|
14
|
+
pkg/natural_key-0.1.0/Rakefile
|
15
|
+
pkg/natural_key-0.1.0/VERSION.yml
|
16
|
+
pkg/natural_key-0.1.0/lib/natural_key.rb
|
17
|
+
pkg/natural_key-0.1.0/lib/natural_key/base.rb
|
18
|
+
pkg/natural_key-0.1.0/natural_key.gemspec
|
19
|
+
pkg/natural_key-0.1.0/test/database.yml
|
20
|
+
pkg/natural_key-0.1.0/test/fixtures/schema.rb
|
21
|
+
pkg/natural_key-0.1.0/test/lib/activerecord_test_case.rb
|
22
|
+
pkg/natural_key-0.1.0/test/lib/activerecord_test_connector.rb
|
23
|
+
pkg/natural_key-0.1.0/test/test_helper.rb
|
24
|
+
pkg/natural_key-0.1.0/test/test_natural_key.rb
|
25
|
+
test/database.yml
|
26
|
+
test/fixtures/schema.rb
|
27
|
+
test/lib/activerecord_test_case.rb
|
28
|
+
test/lib/activerecord_test_connector.rb
|
29
|
+
test/test_helper.rb
|
30
|
+
test/test_natural_key.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= natural_key
|
2
|
+
|
3
|
+
* http://www.pathf.com
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
This gem adds create_or_update functionality to ActiveRecord based on a user-defined natural-key.
|
8
|
+
|
9
|
+
== SYNOPSIS:
|
10
|
+
|
11
|
+
Define natural key for your model as follows:
|
12
|
+
|
13
|
+
#
|
14
|
+
# Table users(first_name varchar, last_name varchar, age integer, address string, salary integer)
|
15
|
+
#
|
16
|
+
class User < ActiveRecord::Base
|
17
|
+
natural_key :first_name, :last_name
|
18
|
+
end
|
19
|
+
|
20
|
+
With this in place, a method 'create_or_update_by_natural_key' can be used to invoke create/update.
|
21
|
+
|
22
|
+
User.create_or_update_by_natural_key(:first_name => 'John', :last_name => "Smith", :age => 25, :address => "New York")
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
gem sources -a http://gems.github.com
|
27
|
+
gem install sjain-natural_key
|
28
|
+
|
29
|
+
== LICENSE:
|
30
|
+
|
31
|
+
(The MIT License)
|
32
|
+
|
33
|
+
Copyright (c) 2009 Pathfinder Associates, LLC.
|
34
|
+
|
35
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
36
|
+
a copy of this software and associated documentation files (the
|
37
|
+
'Software'), to deal in the Software without restriction, including
|
38
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
39
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
40
|
+
permit persons to whom the Software is furnished to do so, subject to
|
41
|
+
the following conditions:
|
42
|
+
|
43
|
+
The above copyright notice and this permission notice shall be
|
44
|
+
included in all copies or substantial portions of the Software.
|
45
|
+
|
46
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
47
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
48
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
49
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
50
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
51
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
52
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
require 'lib/natural_key'
|
5
|
+
|
6
|
+
Echoe.new('natural_key', NaturalKey::VERSION) do |p|
|
7
|
+
p.description = "ActiveRecord.create_or_update based on a user-defined natural-key"
|
8
|
+
p.url = "http://github.com/sjain/natural_key"
|
9
|
+
p.author = "Sharad Jain"
|
10
|
+
p.email = "shaanjain@gmail.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "nbproject/**/*"]
|
12
|
+
p.development_dependencies = []
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/VERSION.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'activerecord'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class Base
|
5
|
+
class_inheritable_accessor :key_attributes
|
6
|
+
class << self
|
7
|
+
def natural_key(*key_attributes)
|
8
|
+
# TODO validate the supplied key_attributes are subset of all attributes
|
9
|
+
# TODO key_attributes should default to primary_key/surrogate_key (:id)
|
10
|
+
# TODO if natural_key is composed of non-primary-key, then it should not contain primary_key
|
11
|
+
raise "natural key attributes cannot be empty" if key_attributes.empty?
|
12
|
+
self.key_attributes = key_attributes
|
13
|
+
end
|
14
|
+
# can't use method "create_or_update" since there is already a private method with that name
|
15
|
+
# in ActiveRecord::Base
|
16
|
+
# TODO The following method should only be made available when natural_key is called with proper
|
17
|
+
# attributes. (hint: use class_eval?)
|
18
|
+
def create_or_update_by_natural_key(options)
|
19
|
+
options.symbolize_keys!
|
20
|
+
#TODO options should contain all key_attributes, and their values should be non-nil
|
21
|
+
key_options = options.reject { |k,v| !key_attributes.include?(k) }
|
22
|
+
raise "key_options cannot be empty" if key_options.empty?
|
23
|
+
record = find(:first, :conditions => key_options)
|
24
|
+
if(record.nil?)
|
25
|
+
record = create(options)
|
26
|
+
else
|
27
|
+
record.update_attributes!(options)
|
28
|
+
end
|
29
|
+
record
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/natural_key.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module NaturalKey
|
5
|
+
version = YAML.load_file(File.dirname(__FILE__) + "/../VERSION.yml")
|
6
|
+
VERSION = "#{version[:major]}.#{version[:minor]}.#{version[:patch]}"
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'natural_key/base'
|
data/natural_key.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{natural_key}
|
5
|
+
s.version = "0.2.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Sharad Jain"]
|
9
|
+
s.date = %q{2009-10-30}
|
10
|
+
s.description = %q{ActiveRecord.create_or_update based on a user-defined natural-key}
|
11
|
+
s.email = %q{shaanjain@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.rdoc", "lib/natural_key.rb", "lib/natural_key/base.rb"]
|
13
|
+
s.files = ["CHANGELOG", "Manifest", "README.rdoc", "Rakefile", "VERSION.yml", "lib/natural_key.rb", "lib/natural_key/base.rb", "natural_key.gemspec", "pkg/natural_key-0.1.0.gem", "pkg/natural_key-0.1.0.tar.gz", "pkg/natural_key-0.1.0/CHANGELOG", "pkg/natural_key-0.1.0/Manifest", "pkg/natural_key-0.1.0/README.rdoc", "pkg/natural_key-0.1.0/Rakefile", "pkg/natural_key-0.1.0/VERSION.yml", "pkg/natural_key-0.1.0/lib/natural_key.rb", "pkg/natural_key-0.1.0/lib/natural_key/base.rb", "pkg/natural_key-0.1.0/natural_key.gemspec", "pkg/natural_key-0.1.0/test/database.yml", "pkg/natural_key-0.1.0/test/fixtures/schema.rb", "pkg/natural_key-0.1.0/test/lib/activerecord_test_case.rb", "pkg/natural_key-0.1.0/test/lib/activerecord_test_connector.rb", "pkg/natural_key-0.1.0/test/test_helper.rb", "pkg/natural_key-0.1.0/test/test_natural_key.rb", "test/database.yml", "test/fixtures/schema.rb", "test/lib/activerecord_test_case.rb", "test/lib/activerecord_test_connector.rb", "test/test_helper.rb", "test/test_natural_key.rb"]
|
14
|
+
s.homepage = %q{http://github.com/sjain/natural_key}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Natural_key", "--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{natural_key}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{ActiveRecord.create_or_update based on a user-defined natural-key}
|
20
|
+
s.test_files = ["test/test_helper.rb", "test/test_natural_key.rb"]
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
else
|
28
|
+
end
|
29
|
+
else
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
VERSION.yml
|
6
|
+
lib/natural_key.rb
|
7
|
+
lib/natural_key/base.rb
|
8
|
+
natural_key.gemspec
|
9
|
+
pkg/natural_key-0.1.0.gem
|
10
|
+
pkg/natural_key-0.1.0.tar.gz
|
11
|
+
pkg/natural_key-0.1.0/CHANGELOG
|
12
|
+
pkg/natural_key-0.1.0/Manifest
|
13
|
+
pkg/natural_key-0.1.0/README.rdoc
|
14
|
+
pkg/natural_key-0.1.0/Rakefile
|
15
|
+
pkg/natural_key-0.1.0/VERSION.yml
|
16
|
+
pkg/natural_key-0.1.0/lib/natural_key.rb
|
17
|
+
pkg/natural_key-0.1.0/lib/natural_key/base.rb
|
18
|
+
pkg/natural_key-0.1.0/natural_key.gemspec
|
19
|
+
pkg/natural_key-0.1.0/test/database.yml
|
20
|
+
pkg/natural_key-0.1.0/test/fixtures/schema.rb
|
21
|
+
pkg/natural_key-0.1.0/test/lib/activerecord_test_case.rb
|
22
|
+
pkg/natural_key-0.1.0/test/lib/activerecord_test_connector.rb
|
23
|
+
pkg/natural_key-0.1.0/test/test_helper.rb
|
24
|
+
pkg/natural_key-0.1.0/test/test_natural_key.rb
|
25
|
+
test/database.yml
|
26
|
+
test/fixtures/schema.rb
|
27
|
+
test/lib/activerecord_test_case.rb
|
28
|
+
test/lib/activerecord_test_connector.rb
|
29
|
+
test/test_helper.rb
|
30
|
+
test/test_natural_key.rb
|
@@ -0,0 +1,52 @@
|
|
1
|
+
= natural_key
|
2
|
+
|
3
|
+
* http://www.pathf.com
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
This gem adds create_or_update functionality to ActiveRecord based on a user-defined natural-key.
|
8
|
+
|
9
|
+
== SYNOPSIS:
|
10
|
+
|
11
|
+
Define natural key for your model as follows:
|
12
|
+
|
13
|
+
#
|
14
|
+
# Table users(first_name varchar, last_name varchar, age integer, address string, salary integer)
|
15
|
+
#
|
16
|
+
class User < ActiveRecord::Base
|
17
|
+
natural_key :first_name, :last_name
|
18
|
+
end
|
19
|
+
|
20
|
+
With this in place, a method 'create_or_update_by_natural_key' can be used to invoke create/update.
|
21
|
+
|
22
|
+
User.create_or_update_by_natural_key(:first_name => 'John', :last_name => "Smith", :age => 25, :address => "New York")
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
gem sources -a http://gems.github.com
|
27
|
+
gem install sjain-natural_key
|
28
|
+
|
29
|
+
== LICENSE:
|
30
|
+
|
31
|
+
(The MIT License)
|
32
|
+
|
33
|
+
Copyright (c) 2009 Pathfinder Associates, LLC.
|
34
|
+
|
35
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
36
|
+
a copy of this software and associated documentation files (the
|
37
|
+
'Software'), to deal in the Software without restriction, including
|
38
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
39
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
40
|
+
permit persons to whom the Software is furnished to do so, subject to
|
41
|
+
the following conditions:
|
42
|
+
|
43
|
+
The above copyright notice and this permission notice shall be
|
44
|
+
included in all copies or substantial portions of the Software.
|
45
|
+
|
46
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
47
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
48
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
49
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
50
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
51
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
52
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
require 'lib/natural_key'
|
5
|
+
|
6
|
+
Echoe.new('natural_key', NaturalKey::VERSION) do |p|
|
7
|
+
p.description = "ActiveRecord.create_or_update based on a user-defined natural-key"
|
8
|
+
p.url = "http://github.com/sjain/natural_key"
|
9
|
+
p.author = "Sharad Jain"
|
10
|
+
p.email = "shaanjain@gmail.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "nbproject/**/*"]
|
12
|
+
p.development_dependencies = []
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'activerecord'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class Base
|
5
|
+
class_inheritable_accessor :key_attributes
|
6
|
+
class << self
|
7
|
+
def natural_key(*key_attributes)
|
8
|
+
# TODO validate the supplied key_attributes are subset of all attributes
|
9
|
+
# TODO key_attributes should default to primary_key/surrogate_key (:id)
|
10
|
+
# TODO if natural_key is composed of non-primary-key, then it should not contain primary_key
|
11
|
+
raise "natural key attributes cannot be empty" if key_attributes.empty?
|
12
|
+
self.key_attributes = key_attributes
|
13
|
+
end
|
14
|
+
# can't use method "create_or_update" since there is already a private method with that name
|
15
|
+
# in ActiveRecord::Base
|
16
|
+
# TODO The following method should only be made available when natural_key is called with proper
|
17
|
+
# attributes. (hint: use class_eval?)
|
18
|
+
def create_or_update_by_natural_key(options)
|
19
|
+
options.symbolize_keys!
|
20
|
+
#TODO options should contain all key_attributes, and their values should be non-nil
|
21
|
+
key_options = options.reject { |k,v| !key_attributes.include?(k) }
|
22
|
+
raise "key_options cannot be empty" if key_options.empty?
|
23
|
+
record = find(:first, :conditions => key_options)
|
24
|
+
if(record.nil?)
|
25
|
+
record = create(options)
|
26
|
+
else
|
27
|
+
record.update_attributes!(options)
|
28
|
+
end
|
29
|
+
record
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module NaturalKey
|
5
|
+
version = YAML.load_file(File.dirname(__FILE__) + "/../VERSION.yml")
|
6
|
+
VERSION = "#{version[:major]}.#{version[:minor]}.#{version[:patch]}"
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'natural_key/base'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{natural_key}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Sharad Jain"]
|
9
|
+
s.date = %q{2009-08-08}
|
10
|
+
s.description = %q{ActiveRecord.create_or_update based on a user-defined natural-key}
|
11
|
+
s.email = %q{shaanjain@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.rdoc", "lib/natural_key/base.rb", "lib/natural_key.rb"]
|
13
|
+
s.files = ["CHANGELOG", "Rakefile", "README.rdoc", "Manifest", "lib/natural_key/base.rb", "lib/natural_key.rb", "test/fixtures/schema.rb", "test/test_helper.rb", "test/database.yml", "test/test_natural_key.rb", "test/lib/activerecord_test_connector.rb", "test/lib/activerecord_test_case.rb", "VERSION.yml", "natural_key.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/sjain/natural_key}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Natural_key", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{natural_key}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{ActiveRecord.create_or_update based on a user-defined natural-key}
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/test_natural_key.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
mysql:
|
2
|
+
adapter: mysql
|
3
|
+
username: arnk
|
4
|
+
password: arnk
|
5
|
+
encoding: utf8
|
6
|
+
database: ar_natural_key_test
|
7
|
+
host: 127.0.0.1
|
8
|
+
|
9
|
+
sqlite3:
|
10
|
+
database: ":memory:"
|
11
|
+
adapter: sqlite3
|
12
|
+
timeout: 500
|
13
|
+
|
14
|
+
sqlite2:
|
15
|
+
database: ":memory:"
|
16
|
+
adapter: sqlite2
|
17
|
+
|
18
|
+
postgres:
|
19
|
+
adapter: postgresql
|
20
|
+
username: postgres
|
21
|
+
password: postgres
|
22
|
+
database: arnk_test
|
23
|
+
min_messages: warning
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'lib/activerecord_test_connector'
|
2
|
+
|
3
|
+
class ActiveRecordTestCase < ActiveRecord::TestCase
|
4
|
+
include ActiveRecord::TestFixtures
|
5
|
+
|
6
|
+
# Set our fixture path
|
7
|
+
if ActiveRecordTestConnector.able_to_connect
|
8
|
+
self.fixture_path = File.join(File.dirname(__FILE__), '..', 'fixtures')
|
9
|
+
self.use_transactional_fixtures = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.fixtures(*args)
|
13
|
+
super if ActiveRecordTestConnector.connected
|
14
|
+
end
|
15
|
+
|
16
|
+
def run(*args)
|
17
|
+
super if ActiveRecordTestConnector.connected
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def assert_queries(num = 1)
|
23
|
+
$query_count = 0
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_no_queries(&block)
|
30
|
+
assert_queries(0, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ActiveRecordTestConnector.setup
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'active_record/version'
|
4
|
+
require 'active_record/fixtures'
|
5
|
+
|
6
|
+
class ActiveRecordTestConnector
|
7
|
+
cattr_accessor :able_to_connect
|
8
|
+
cattr_accessor :connected
|
9
|
+
|
10
|
+
FIXTURES_PATH = File.join(File.dirname(__FILE__), '..', 'fixtures')
|
11
|
+
|
12
|
+
# Set our defaults
|
13
|
+
self.connected = false
|
14
|
+
self.able_to_connect = true
|
15
|
+
|
16
|
+
def self.setup
|
17
|
+
unless self.connected || !self.able_to_connect
|
18
|
+
setup_connection
|
19
|
+
load_schema
|
20
|
+
add_load_path FIXTURES_PATH
|
21
|
+
self.connected = true
|
22
|
+
end
|
23
|
+
rescue Exception => e # errors from ActiveRecord setup
|
24
|
+
$stderr.puts "\nSkipping ActiveRecord tests: #{e}\n\n"
|
25
|
+
self.able_to_connect = false
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.add_load_path(path)
|
31
|
+
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
32
|
+
dep.load_paths.unshift path
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.setup_connection
|
36
|
+
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
37
|
+
|
38
|
+
configurations = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'database.yml'))
|
39
|
+
raise "no configuration for '#{db}'" unless configurations.key? db
|
40
|
+
configuration = configurations[db]
|
41
|
+
|
42
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
43
|
+
puts "using #{configuration['adapter']} adapter" unless ENV['DB'].blank?
|
44
|
+
|
45
|
+
gem 'sqlite3-ruby' if 'sqlite3' == db
|
46
|
+
|
47
|
+
ActiveRecord::Base.establish_connection(configuration)
|
48
|
+
ActiveRecord::Base.configurations = { db => configuration }
|
49
|
+
prepare ActiveRecord::Base.connection
|
50
|
+
|
51
|
+
unless Object.const_defined?(:QUOTED_TYPE)
|
52
|
+
Object.send :const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.load_schema
|
57
|
+
ActiveRecord::Base.silence do
|
58
|
+
ActiveRecord::Migration.verbose = false
|
59
|
+
load File.join(FIXTURES_PATH, 'schema.rb')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.prepare(conn)
|
64
|
+
class << conn
|
65
|
+
IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SHOW FIELDS /]
|
66
|
+
|
67
|
+
def execute_with_counting(sql, name = nil, &block)
|
68
|
+
$query_count ||= 0
|
69
|
+
$query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
|
70
|
+
execute_without_counting(sql, name, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method_chain :execute, :counting
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'lib/activerecord_test_case'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/natural_key'
|
5
|
+
|
6
|
+
# gem install redgreen for colored test output
|
7
|
+
#begin require 'redgreen'; rescue LoadError; end
|
8
|
+
|
9
|
+
# The following is not required since we use active-record gem installed on the system
|
10
|
+
#require 'boot' unless defined?(ActiveRecord)
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
# any test helper methods can go here
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class User < ActiveRecord::Base
|
4
|
+
natural_key :first_name, :last_name
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestNaturalKey < ActiveRecordTestCase
|
8
|
+
def test_create_by_natural_key
|
9
|
+
created_record = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
10
|
+
updated_record = User.create_or_update_by_natural_key(:first_name => 'Different', :last_name => "Smith", :age => 25, :address => "New York")
|
11
|
+
assert_not_equal(created_record.id, updated_record.id)
|
12
|
+
assert_equal(25, updated_record.age)
|
13
|
+
assert_equal("New York", updated_record.address)
|
14
|
+
end
|
15
|
+
def test_update_by_natural_key
|
16
|
+
created_record = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
17
|
+
updated_record = User.create_or_update_by_natural_key(:first_name => 'John', :last_name => "Smith", :age => 25, :address => "New York")
|
18
|
+
assert_equal(created_record.id, updated_record.id)
|
19
|
+
assert_equal(25, updated_record.age)
|
20
|
+
assert_equal("New York", updated_record.address)
|
21
|
+
end
|
22
|
+
def test_update_by_natural_key_when_keys_are_strings_instead_of_symbols
|
23
|
+
User.create(:first_name => 'Mary', :last_name => "Beth", :age => 21, :address => "Chicago")
|
24
|
+
john_smith = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
25
|
+
updated_record = User.create_or_update_by_natural_key('first_name' => 'John',
|
26
|
+
'last_name' => "Smith",
|
27
|
+
'age' => 25,
|
28
|
+
'address' => "New York")
|
29
|
+
assert_equal(john_smith.id, updated_record.id)
|
30
|
+
assert_equal(25, updated_record.age)
|
31
|
+
assert_equal("New York", updated_record.address)
|
32
|
+
end
|
33
|
+
end
|
Binary file
|
Binary file
|
data/test/database.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
mysql:
|
2
|
+
adapter: mysql
|
3
|
+
username: arnk
|
4
|
+
password: arnk
|
5
|
+
encoding: utf8
|
6
|
+
database: ar_natural_key_test
|
7
|
+
host: 127.0.0.1
|
8
|
+
|
9
|
+
sqlite3:
|
10
|
+
database: ":memory:"
|
11
|
+
adapter: sqlite3
|
12
|
+
timeout: 500
|
13
|
+
|
14
|
+
sqlite2:
|
15
|
+
database: ":memory:"
|
16
|
+
adapter: sqlite2
|
17
|
+
|
18
|
+
postgres:
|
19
|
+
adapter: postgresql
|
20
|
+
username: postgres
|
21
|
+
password: postgres
|
22
|
+
database: arnk_test
|
23
|
+
min_messages: warning
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'lib/activerecord_test_connector'
|
2
|
+
|
3
|
+
class ActiveRecordTestCase < ActiveRecord::TestCase
|
4
|
+
include ActiveRecord::TestFixtures
|
5
|
+
|
6
|
+
# Set our fixture path
|
7
|
+
if ActiveRecordTestConnector.able_to_connect
|
8
|
+
self.fixture_path = File.join(File.dirname(__FILE__), '..', 'fixtures')
|
9
|
+
self.use_transactional_fixtures = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.fixtures(*args)
|
13
|
+
super if ActiveRecordTestConnector.connected
|
14
|
+
end
|
15
|
+
|
16
|
+
def run(*args)
|
17
|
+
super if ActiveRecordTestConnector.connected
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def assert_queries(num = 1)
|
23
|
+
$query_count = 0
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_no_queries(&block)
|
30
|
+
assert_queries(0, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ActiveRecordTestConnector.setup
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'active_record/version'
|
4
|
+
require 'active_record/fixtures'
|
5
|
+
|
6
|
+
class ActiveRecordTestConnector
|
7
|
+
cattr_accessor :able_to_connect
|
8
|
+
cattr_accessor :connected
|
9
|
+
|
10
|
+
FIXTURES_PATH = File.join(File.dirname(__FILE__), '..', 'fixtures')
|
11
|
+
|
12
|
+
# Set our defaults
|
13
|
+
self.connected = false
|
14
|
+
self.able_to_connect = true
|
15
|
+
|
16
|
+
def self.setup
|
17
|
+
unless self.connected || !self.able_to_connect
|
18
|
+
setup_connection
|
19
|
+
load_schema
|
20
|
+
add_load_path FIXTURES_PATH
|
21
|
+
self.connected = true
|
22
|
+
end
|
23
|
+
rescue Exception => e # errors from ActiveRecord setup
|
24
|
+
$stderr.puts "\nSkipping ActiveRecord tests: #{e}\n\n"
|
25
|
+
self.able_to_connect = false
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.add_load_path(path)
|
31
|
+
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
32
|
+
dep.load_paths.unshift path
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.setup_connection
|
36
|
+
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
37
|
+
|
38
|
+
configurations = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'database.yml'))
|
39
|
+
raise "no configuration for '#{db}'" unless configurations.key? db
|
40
|
+
configuration = configurations[db]
|
41
|
+
|
42
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
43
|
+
puts "using #{configuration['adapter']} adapter" unless ENV['DB'].blank?
|
44
|
+
|
45
|
+
gem 'sqlite3-ruby' if 'sqlite3' == db
|
46
|
+
|
47
|
+
ActiveRecord::Base.establish_connection(configuration)
|
48
|
+
ActiveRecord::Base.configurations = { db => configuration }
|
49
|
+
prepare ActiveRecord::Base.connection
|
50
|
+
|
51
|
+
unless Object.const_defined?(:QUOTED_TYPE)
|
52
|
+
Object.send :const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.load_schema
|
57
|
+
ActiveRecord::Base.silence do
|
58
|
+
ActiveRecord::Migration.verbose = false
|
59
|
+
load File.join(FIXTURES_PATH, 'schema.rb')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.prepare(conn)
|
64
|
+
class << conn
|
65
|
+
IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SHOW FIELDS /]
|
66
|
+
|
67
|
+
def execute_with_counting(sql, name = nil, &block)
|
68
|
+
$query_count ||= 0
|
69
|
+
$query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
|
70
|
+
execute_without_counting(sql, name, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method_chain :execute, :counting
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'lib/activerecord_test_case'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/natural_key'
|
5
|
+
|
6
|
+
# gem install redgreen for colored test output
|
7
|
+
#begin require 'redgreen'; rescue LoadError; end
|
8
|
+
|
9
|
+
# The following is not required since we use active-record gem installed on the system
|
10
|
+
#require 'boot' unless defined?(ActiveRecord)
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
# any test helper methods can go here
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class User < ActiveRecord::Base
|
4
|
+
natural_key :first_name, :last_name
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestNaturalKey < ActiveRecordTestCase
|
8
|
+
def test_create_by_natural_key
|
9
|
+
created_record = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
10
|
+
updated_record = User.create_or_update_by_natural_key(:first_name => 'Different', :last_name => "Smith", :age => 25, :address => "New York")
|
11
|
+
assert_not_equal(created_record.id, updated_record.id)
|
12
|
+
assert_equal(25, updated_record.age)
|
13
|
+
assert_equal("New York", updated_record.address)
|
14
|
+
end
|
15
|
+
def test_update_by_natural_key
|
16
|
+
created_record = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
17
|
+
updated_record = User.create_or_update_by_natural_key(:first_name => 'John', :last_name => "Smith", :age => 25, :address => "New York")
|
18
|
+
assert_equal(created_record.id, updated_record.id)
|
19
|
+
assert_equal(25, updated_record.age)
|
20
|
+
assert_equal("New York", updated_record.address)
|
21
|
+
end
|
22
|
+
def test_update_by_natural_key_when_keys_are_strings_instead_of_symbols
|
23
|
+
User.create(:first_name => 'Mary', :last_name => "Beth", :age => 21, :address => "Chicago")
|
24
|
+
john_smith = User.create(:first_name => 'John', :last_name => "Smith", :age => 21, :address => "Chicago")
|
25
|
+
updated_record = User.create_or_update_by_natural_key('first_name' => 'John',
|
26
|
+
'last_name' => "Smith",
|
27
|
+
'age' => 25,
|
28
|
+
'address' => "New York")
|
29
|
+
assert_equal(john_smith.id, updated_record.id)
|
30
|
+
assert_equal(25, updated_record.age)
|
31
|
+
assert_equal("New York", updated_record.address)
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: natural_key
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sharad Jain
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-30 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ActiveRecord.create_or_update based on a user-defined natural-key
|
17
|
+
email: shaanjain@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- README.rdoc
|
25
|
+
- lib/natural_key.rb
|
26
|
+
- lib/natural_key/base.rb
|
27
|
+
files:
|
28
|
+
- CHANGELOG
|
29
|
+
- Manifest
|
30
|
+
- README.rdoc
|
31
|
+
- Rakefile
|
32
|
+
- VERSION.yml
|
33
|
+
- lib/natural_key.rb
|
34
|
+
- lib/natural_key/base.rb
|
35
|
+
- natural_key.gemspec
|
36
|
+
- pkg/natural_key-0.1.0.gem
|
37
|
+
- pkg/natural_key-0.1.0.tar.gz
|
38
|
+
- pkg/natural_key-0.1.0/CHANGELOG
|
39
|
+
- pkg/natural_key-0.1.0/Manifest
|
40
|
+
- pkg/natural_key-0.1.0/README.rdoc
|
41
|
+
- pkg/natural_key-0.1.0/Rakefile
|
42
|
+
- pkg/natural_key-0.1.0/VERSION.yml
|
43
|
+
- pkg/natural_key-0.1.0/lib/natural_key.rb
|
44
|
+
- pkg/natural_key-0.1.0/lib/natural_key/base.rb
|
45
|
+
- pkg/natural_key-0.1.0/natural_key.gemspec
|
46
|
+
- pkg/natural_key-0.1.0/test/database.yml
|
47
|
+
- pkg/natural_key-0.1.0/test/fixtures/schema.rb
|
48
|
+
- pkg/natural_key-0.1.0/test/lib/activerecord_test_case.rb
|
49
|
+
- pkg/natural_key-0.1.0/test/lib/activerecord_test_connector.rb
|
50
|
+
- pkg/natural_key-0.1.0/test/test_helper.rb
|
51
|
+
- pkg/natural_key-0.1.0/test/test_natural_key.rb
|
52
|
+
- test/database.yml
|
53
|
+
- test/fixtures/schema.rb
|
54
|
+
- test/lib/activerecord_test_case.rb
|
55
|
+
- test/lib/activerecord_test_connector.rb
|
56
|
+
- test/test_helper.rb
|
57
|
+
- test/test_natural_key.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/sjain/natural_key
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --line-numbers
|
65
|
+
- --inline-source
|
66
|
+
- --title
|
67
|
+
- Natural_key
|
68
|
+
- --main
|
69
|
+
- README.rdoc
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "1.2"
|
83
|
+
version:
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project: natural_key
|
87
|
+
rubygems_version: 1.3.5
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: ActiveRecord.create_or_update based on a user-defined natural-key
|
91
|
+
test_files:
|
92
|
+
- test/test_helper.rb
|
93
|
+
- test/test_natural_key.rb
|