natural_key 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ == 0.1.0 2009-01-07
2
+ * fixed to accept hash with string keys in addition to symbols
3
+ * cleaned up unnecessary files
4
+ * using Echoe instead of newgem for gem generation
5
+ * github updated
6
+
7
+ == 0.0.1 2009-01-07
8
+ * initial release
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,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 2
4
+ :patch: 0
@@ -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,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,8 @@
1
+ == 0.1.0 2009-01-07
2
+ * fixed to accept hash with string keys in addition to symbols
3
+ * cleaned up unnecessary files
4
+ * using Echoe instead of newgem for gem generation
5
+ * github updated
6
+
7
+ == 0.0.1 2009-01-07
8
+ * initial release
@@ -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,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 2
4
+ :patch: 0
@@ -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,9 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :users, :force => true do |t|
3
+ t.string :first_name
4
+ t.string :last_name
5
+ t.integer :age
6
+ t.string :address
7
+ t.integer :salary, :default => 70000
8
+ end
9
+ end
@@ -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,9 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :users, :force => true do |t|
3
+ t.string :first_name
4
+ t.string :last_name
5
+ t.integer :age
6
+ t.string :address
7
+ t.integer :salary, :default => 70000
8
+ end
9
+ end
@@ -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
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