composite_primary_keys 3.0.4 → 3.0.7

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/History.txt CHANGED
@@ -1,3 +1,19 @@
1
+ == 3.0.7 2010-11-29
2
+ * Fix has and belongs to many associations implementation.
3
+
4
+
5
+ == 3.0.6 2010-11-29 (yanked)
6
+ * Add full support for has and belongs to many associations.
7
+
8
+
9
+ == 3.0.5 2010-11-28 (yanked)
10
+ * Apply patch from Marian Rudzynski for fixing up attribute_methods/primary_key
11
+ * Apply patch from Toby Cabot to fix up various sqlite3 issues
12
+ * Add partial support for has and belongs to many associations. Currently a cpk model
13
+ can have a habtm, but a normal model cannot have a habtm to a cpk model (its actually
14
+ not too hard to add, but one step at a time...)
15
+
16
+
1
17
  == 3.0.4 2010-11-21
2
18
  * Support deleting records when dependent is set to :delete_all
3
19
  * Switch the method #id to return a CompositeKeys instance (thus going back to how
data/Rakefile CHANGED
@@ -10,46 +10,13 @@ require 'rake/gempackagetask'
10
10
  PROJECT_ROOT = File.expand_path(".")
11
11
  GEM_NAME = 'composite_primary_keys'
12
12
 
13
- # Read the current version
14
- require File.join(File.dirname(__FILE__), 'lib', 'composite_primary_keys', 'version')
13
+ # Read the spec file
14
+ spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
15
15
 
16
- # Setup Gem Specs
17
- spec = Gem::Specification.new do |s|
18
- s.name = GEM_NAME
19
- s.version = CompositePrimaryKeys::VERSION::STRING
20
- s.platform = Gem::Platform::RUBY
21
- s.authors = ["Dr Nic Williams", "Charlie Savage"]
22
- s.email = ["drnicwilliams@gmail.com"]
23
- s.homepage = "http://github.com/cfis/composite_primary_keys"
24
- s.summary = "Composite key support for ActiveRecord"
25
- s.rubyforge_project = 'compositekeys'
26
- s.description = "Composite key support for ActiveRecord 3"
27
- s.files = FileList['Rakefile',
28
- '*.txt',
29
- '*.rb',
30
- 'lib/**/*',
31
- 'local/**/*',
32
- 'scripts/**/*',
33
- 'tasks/**/*',
34
- 'test/**/*'].to_a
35
- s.require_path = 'lib'
36
- s.test_files = Dir.glob("test/**")
16
+ # Setup Rake tasks for managing the gem
17
+ Rake::GemPackageTask.new(spec).define
37
18
 
38
- s.date = Time.new
39
- s.has_rdoc = true
40
-
41
- # Dependencies
42
- s.required_ruby_version = '>= 1.8.7'
43
- s.add_dependency('activerecord', '>= 3.0.3')
44
- s.add_development_dependency "rspec"
45
- end
46
-
47
- # Rake task to build the default package
48
- Rake::GemPackageTask.new(spec) do |pkg|
49
- pkg.need_tar = true
50
- end
51
-
52
- # Load task files
19
+ # Now load in other task files
53
20
  Dir.glob('tasks/**/*.rake').each do |rake_file|
54
21
  load File.join(File.dirname(__FILE__), rake_file)
55
22
  end
@@ -45,6 +45,7 @@ require 'active_record/associations/has_one_association'
45
45
  require 'active_record/associations/has_one_through_association'
46
46
  require 'active_record/associations/through_association_scope'
47
47
  require 'active_record/relation/query_methods'
48
+ require 'active_record/attribute_methods/primary_key'
48
49
 
49
50
  require 'composite_primary_keys/fixtures'
50
51
  require 'composite_primary_keys/composite_arrays'
@@ -63,6 +64,7 @@ require 'composite_primary_keys/base'
63
64
  require 'composite_primary_keys/calculations'
64
65
  require 'composite_primary_keys/validations/uniqueness'
65
66
  require 'composite_primary_keys/query_methods'
67
+ require 'composite_primary_keys/primary_key'
66
68
 
67
69
  Dir[File.dirname(__FILE__) + '/composite_primary_keys/connection_adapters/*.rb'].each do |adapter|
68
70
  begin
@@ -25,6 +25,69 @@ module ActiveRecord
25
25
 
26
26
  construct_counter_sql
27
27
  end
28
+
29
+ def insert_record(record, force = true, validate = true)
30
+ unless record.persisted?
31
+ if force
32
+ record.save!
33
+ else
34
+ return false unless record.save(:validate => validate)
35
+ end
36
+ end
37
+
38
+ if @reflection.options[:insert_sql]
39
+ @owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
40
+ else
41
+ relation = Arel::Table.new(@reflection.options[:join_table])
42
+ timestamps = record_timestamp_columns(record)
43
+ timezone = record.send(:current_time_from_proper_timezone) if timestamps.any?
44
+
45
+ # CPK
46
+ #attributes = Hash[columns.map do |column|
47
+ # name = column.name
48
+ # value = case name.to_s
49
+ # when @reflection.primary_key_name.to_s
50
+ # @owner.id
51
+ # when @reflection.association_foreign_key.to_s
52
+ # record.id
53
+ # when *timestamps
54
+ # timezone
55
+ # else
56
+ # @owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
57
+ # end
58
+ # [relation[name], value] unless value.nil?
59
+ #end]
60
+
61
+ # CPK
62
+ owner_foreign_keys = @reflection.cpk_primary_key.map{|key| key.to_s}
63
+ association_foreign_keys = Array(@reflection.association_foreign_key).map{|key| key.to_s}
64
+
65
+ attributes = Hash[columns.map do |column|
66
+ name = column.name.to_s
67
+ value = case
68
+ when owner_foreign_keys.include?(name)
69
+ index = owner_foreign_keys.index(name)
70
+ primary_keys = Array(@owner.class.primary_key)
71
+ primary_key = primary_keys[index]
72
+ @owner[primary_key]
73
+ when association_foreign_keys.include?(name)
74
+ index = association_foreign_keys.index(name)
75
+ primary_keys = Array(@reflection.klass.primary_key)
76
+ primary_key = primary_keys[index]
77
+ record[primary_key]
78
+ when timestamps.include?(name)
79
+ timezone
80
+ else
81
+ @owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
82
+ end
83
+ [relation[name], value] unless value.nil?
84
+ end]
85
+
86
+ relation.insert(attributes)
87
+ end
88
+
89
+ return true
90
+ end
28
91
  end
29
92
  end
30
93
  end
@@ -1,4 +1,4 @@
1
- require 'active_record/connection_adapters/sqlite_adapter'
1
+ require 'active_record/connection_adapters/sqlite3_adapter'
2
2
 
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters #:nodoc:
@@ -12,4 +12,4 @@ module ActiveRecord
12
12
  end
13
13
  end
14
14
  end
15
- end
15
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ module AttributeMethods #:nodoc:
3
+ module PrimaryKey
4
+ def to_key
5
+ # CPK
6
+ #key = send(self.class.primary_key)
7
+ #[key] if key
8
+
9
+ primary_key = self.class.primary_key
10
+ if primary_key.is_a?(Array)
11
+ primary_key.collect{|k| send(k)}
12
+ else
13
+ key = send(primary_key)
14
+ [key] if key
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
- TINY = 4
5
+ TINY = 7
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
data/scripts/txt2html CHANGED
@@ -7,7 +7,7 @@ require 'erb'
7
7
  require File.dirname(__FILE__) + '/../lib/composite_primary_keys/version.rb'
8
8
 
9
9
  version = CompositePrimaryKeys::VERSION::STRING
10
- download = 'http://rubyforge.org/projects/compositekeys'
10
+ download = 'http://rubygems.org/gems/composite_primary_keys'
11
11
 
12
12
  class Fixnum
13
13
  def ordinal
data/scripts/txt2js CHANGED
@@ -8,7 +8,7 @@ require 'active_support'
8
8
  require File.dirname(__FILE__) + '/../lib/composite_primary_keys/version.rb'
9
9
 
10
10
  version = CompositePrimaryKeys::VERSION::STRING
11
- download = 'http://rubyforge.org/projects/compositekeys'
11
+ download = 'http://rubygems.org/gems/composite_primary_keys'
12
12
 
13
13
  class Fixnum
14
14
  def ordinal
@@ -23,6 +23,6 @@ namespace :sqlite3 do
23
23
  task :rebuild_databases => [:drop_databases, :build_databases]
24
24
 
25
25
  task :load_connection do
26
- require File.join(PROJECT_ROOT, "test", "connections", "native_sqlite3", "connection")
26
+ require File.join(PROJECT_ROOT, "test", "connections", "native_sqlite", "connection")
27
27
  end
28
28
  end
data/tasks/website.rake CHANGED
@@ -8,11 +8,11 @@ end
8
8
  desc 'Upload website files to rubyforge'
9
9
  task :website_upload do
10
10
  config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
11
- host = "#{config["username"]}@rubyforge.org"
12
- remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
11
+ host = "cfis@rubyforge.org"
12
+ remote_dir = "/var/www/gforge-projects/compositekeys"
13
13
  local_dir = 'website'
14
- sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
14
+ sh %{scp -r #{local_dir}/* #{host}:#{remote_dir}}
15
15
  end
16
16
 
17
17
  desc 'Generate and upload website files'
18
- task :website => [:website_generate, :website_upload, :publish_docs]
18
+ task :website => [:website_generate, :website_upload]
@@ -4,6 +4,7 @@ mysql:
4
4
 
5
5
  sqlite3:
6
6
  adapter: sqlite3
7
+ dbfile: db/composite_primary_keys_unittest.sqlite3
7
8
 
8
9
  postgresql:
9
10
  adapter: postgresql
@@ -5,6 +5,7 @@ mysql:
5
5
 
6
6
  sqlite3:
7
7
  adapter: sqlite3
8
+ dbfile: db/composite_primary_keys_unittest.sqlite3
8
9
 
9
10
  postgresql:
10
11
  adapter: postgresql
@@ -1,13 +1,13 @@
1
1
  print "Using native Sqlite3\n"
2
2
  require 'logger'
3
- require 'adapter_helper/sqlite3'
4
3
  require 'active_record'
4
+ require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
5
5
 
6
6
  ActiveRecord::Base.logger = Logger.new("debug.log")
7
7
 
8
8
  def connection_string
9
- connection_SPEC['dbfile']
9
+ SPEC['dbfile']
10
10
  end
11
11
 
12
12
  SPEC = CompositePrimaryKeys::ConnectionSpec[:sqlite3]
13
- ActiveRecord::Base.establish_connection(SPEC)
13
+ ActiveRecord::Base.establish_connection(SPEC)
data/test/debug.log CHANGED
@@ -450,3 +450,112 @@ HINT: No operator matches the given name and argument type(s). You might need t
450
450
  SQL (0.0ms) SET standard_conforming_strings = on
451
451
  SQL (0.0ms) SET client_min_messages TO 'notice'
452
452
  SQL (0.0ms) SHOW TIME ZONE
453
+ SQL (0.0ms) SHOW client_min_messages
454
+ SQL (0.0ms) SET client_min_messages TO 'panic'
455
+ SQL (0.0ms) SET standard_conforming_strings = on
456
+ SQL (0.0ms) SET client_min_messages TO 'notice'
457
+ SQL (0.0ms) SHOW TIME ZONE
458
+ SQL (1.0ms) SHOW client_min_messages
459
+ SQL (0.0ms) SET client_min_messages TO 'panic'
460
+ SQL (0.0ms) SET standard_conforming_strings = on
461
+ SQL (1.0ms) SET client_min_messages TO 'notice'
462
+ SQL (0.0ms) SHOW TIME ZONE
463
+ PGError: ERROR: null value in column "franchise_id" violates not-null constraint
464
+ : INSERT INTO "restaurants_suburbs" ("suburb_id", "city_id") VALUES (22, 22)
465
+ SQL (0.0ms) SHOW client_min_messages
466
+ SQL (1.0ms) SET client_min_messages TO 'panic'
467
+ SQL (0.0ms) SET standard_conforming_strings = on
468
+ SQL (0.0ms) SET client_min_messages TO 'notice'
469
+ SQL (0.0ms) SHOW TIME ZONE
470
+ SQL (0.0ms) SHOW client_min_messages
471
+ SQL (0.0ms) SET client_min_messages TO 'panic'
472
+ SQL (0.0ms) SET standard_conforming_strings = on
473
+ SQL (1.0ms) SET client_min_messages TO 'notice'
474
+ SQL (0.0ms) SHOW TIME ZONE
475
+ SQL (0.0ms) SHOW client_min_messages
476
+ SQL (0.0ms) SET client_min_messages TO 'panic'
477
+ SQL (0.0ms) SET standard_conforming_strings = on
478
+ SQL (0.0ms) SET client_min_messages TO 'notice'
479
+ SQL (0.0ms) SHOW TIME ZONE
480
+ SQL (1.0ms) SHOW client_min_messages
481
+ SQL (0.0ms) SET client_min_messages TO 'panic'
482
+ SQL (0.0ms) SET standard_conforming_strings = on
483
+ SQL (0.0ms) SET client_min_messages TO 'notice'
484
+ SQL (1.0ms) SHOW TIME ZONE
485
+ SQL (0.0ms) SHOW client_min_messages
486
+ SQL (1.0ms) SET client_min_messages TO 'panic'
487
+ SQL (0.0ms) SET standard_conforming_strings = on
488
+ SQL (0.0ms) SET client_min_messages TO 'notice'
489
+ SQL (0.0ms) SHOW TIME ZONE
490
+ SQL (1.0ms) SHOW client_min_messages
491
+ SQL (1.0ms) SET client_min_messages TO 'panic'
492
+ SQL (0.0ms) SET standard_conforming_strings = on
493
+ SQL (0.0ms) SET client_min_messages TO 'notice'
494
+ SQL (0.0ms) SHOW TIME ZONE
495
+ SQL (1.0ms) SHOW client_min_messages
496
+ SQL (1.0ms) SET client_min_messages TO 'panic'
497
+ SQL (0.0ms) SET standard_conforming_strings = on
498
+ SQL (0.0ms) SET client_min_messages TO 'notice'
499
+ SQL (1.0ms) SHOW TIME ZONE
500
+ SQL (0.0ms) SHOW client_min_messages
501
+ SQL (0.0ms) SET client_min_messages TO 'panic'
502
+ SQL (0.0ms) SET standard_conforming_strings = on
503
+ SQL (0.0ms) SET client_min_messages TO 'notice'
504
+ SQL (0.0ms) SHOW TIME ZONE
505
+ SQL (0.0ms) SHOW client_min_messages
506
+ SQL (1.0ms) SET client_min_messages TO 'panic'
507
+ SQL (0.0ms) SET standard_conforming_strings = on
508
+ SQL (0.0ms) SET client_min_messages TO 'notice'
509
+ SQL (0.0ms) SHOW TIME ZONE
510
+ SQL (0.0ms) SHOW client_min_messages
511
+ SQL (0.0ms) SET client_min_messages TO 'panic'
512
+ SQL (0.0ms) SET standard_conforming_strings = on
513
+ SQL (0.0ms) SET client_min_messages TO 'notice'
514
+ SQL (0.0ms) SHOW TIME ZONE
515
+ SQL (1.0ms) SHOW client_min_messages
516
+ SQL (0.0ms) SET client_min_messages TO 'panic'
517
+ SQL (0.0ms) SET standard_conforming_strings = on
518
+ SQL (1.0ms) SET client_min_messages TO 'notice'
519
+ SQL (0.0ms) SHOW TIME ZONE
520
+ SQL (0.0ms) SHOW client_min_messages
521
+ SQL (0.0ms) SET client_min_messages TO 'panic'
522
+ SQL (0.0ms) SET standard_conforming_strings = on
523
+ SQL (0.0ms) SET client_min_messages TO 'notice'
524
+ SQL (1.0ms) SHOW TIME ZONE
525
+ PGError: ERROR: column "tariff_idstart_date" does not exist
526
+ LINE 1: SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LE...
527
+ ^
528
+ : SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LEFT OUTER JOIN "product_tariffs" ON "product_tariffs"."tariff_id" = "tariffs"."tariff_id" AND "product_tariffs"."tariff_start_date" = "tariffs"."start_date"
529
+ PGError: ERROR: operator does not exist: character varying = integer
530
+ LINE 1: ...ments".person_type = 'User') AND ("comments".person_id = 1))
531
+ ^
532
+ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
533
+ : SELECT "hacks".* FROM "hacks" INNER JOIN "comments" ON ("hacks"."name" = "comments"."hack_id") WHERE (("comments".person_type = 'User') AND ("comments".person_id = 1))
534
+ SQL (0.0ms) SHOW client_min_messages
535
+ SQL (0.0ms) SET client_min_messages TO 'panic'
536
+ SQL (0.0ms) SET standard_conforming_strings = on
537
+ SQL (0.0ms) SET client_min_messages TO 'notice'
538
+ SQL (0.0ms) SHOW TIME ZONE
539
+ PGError: ERROR: column "tariff_idstart_date" does not exist
540
+ LINE 1: SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LE...
541
+ ^
542
+ : SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LEFT OUTER JOIN "product_tariffs" ON "product_tariffs"."tariff_id" = "tariffs"."tariff_id" AND "product_tariffs"."tariff_start_date" = "tariffs"."start_date"
543
+ PGError: ERROR: operator does not exist: character varying = integer
544
+ LINE 1: ...ments".person_type = 'User') AND ("comments".person_id = 1))
545
+ ^
546
+ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
547
+ : SELECT "hacks".* FROM "hacks" INNER JOIN "comments" ON ("hacks"."name" = "comments"."hack_id") WHERE (("comments".person_type = 'User') AND ("comments".person_id = 1))
548
+ SQL (0.0ms) SHOW client_min_messages
549
+ SQL (0.0ms) SET client_min_messages TO 'panic'
550
+ SQL (0.0ms) SET standard_conforming_strings = on
551
+ SQL (1.0ms) SET client_min_messages TO 'notice'
552
+ SQL (0.0ms) SHOW TIME ZONE
553
+ PGError: ERROR: column "tariff_idstart_date" does not exist
554
+ LINE 1: SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LE...
555
+ ^
556
+ : SELECT COUNT(DISTINCT tariff_idstart_date) FROM "tariffs" LEFT OUTER JOIN "product_tariffs" ON "product_tariffs"."tariff_id" = "tariffs"."tariff_id" AND "product_tariffs"."tariff_start_date" = "tariffs"."start_date"
557
+ PGError: ERROR: operator does not exist: character varying = integer
558
+ LINE 1: ...ments".person_type = 'User') AND ("comments".person_id = 1))
559
+ ^
560
+ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
561
+ : SELECT "hacks".* FROM "hacks" INNER JOIN "comments" ON ("hacks"."name" = "comments"."hack_id") WHERE (("comments".person_type = 'User') AND ("comments".person_id = 1))
data/test/test_create.rb CHANGED
@@ -13,17 +13,17 @@ class TestCreate < ActiveSupport::TestCase
13
13
  :primary_keys => :reference_type_id,
14
14
  :create => {:reference_type_id => 10, :type_label => 'NEW_TYPE', :abbreviation => 'New Type'}
15
15
  },
16
- :dual => {
16
+ :dual => {
17
17
  :class => ReferenceCode,
18
18
  :primary_keys => [:reference_type_id, :reference_code],
19
19
  :create => {:reference_type_id => 1, :reference_code => 20, :code_label => 'NEW_CODE', :abbreviation => 'New Code'}
20
20
  },
21
21
  }
22
-
22
+
23
23
  def setup
24
24
  self.class.classes = CLASSES
25
25
  end
26
-
26
+
27
27
  def test_setup
28
28
  testing_with do
29
29
  assert_not_nil @klass_info[:create]
@@ -58,11 +58,37 @@ class TestCreate < ActiveSupport::TestCase
58
58
  assert_equal(suburb.city_id, street.city_id)
59
59
  assert_equal(suburb.suburb_id, street.suburb_id)
60
60
  end
61
-
61
+
62
62
  def test_create_on_association_when_belongs_to_is_single_key
63
63
  rt = ReferenceType.find(:first)
64
64
  rt.reference_codes.create(:reference_code => 4321, :code_label => 'foo', :abbreviation => 'bar')
65
65
  rc = ReferenceCode.find_by_reference_code(4321)
66
66
  assert_equal(rc.reference_type_id, rt.reference_type_id)
67
67
  end
68
+
69
+ def test_create_habtm
70
+ restaurant = Restaurant.new(:franchise_id => 22,
71
+ :store_id => 23,
72
+ :name => "My Store")
73
+
74
+ restaurant.suburbs << Suburb.new(:city_id => 24,
75
+ :suburb_id => 25,
76
+ :name => "My Suburb")
77
+
78
+ restaurant.save!
79
+
80
+ restaurant.reload
81
+
82
+ # Test restaurant
83
+ assert_equal(22, restaurant.franchise_id)
84
+ assert_equal(23, restaurant.store_id)
85
+ assert_equal("My Store", restaurant.name)
86
+ assert_equal(1, restaurant.suburbs.length)
87
+
88
+ # Test suburbs
89
+ suburb = restaurant.suburbs[0]
90
+ assert_equal(24, suburb.city_id)
91
+ assert_equal(25, suburb.suburb_id)
92
+ assert_equal("My Suburb", suburb.name)
93
+ end
68
94
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composite_primary_keys
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 9
5
5
  prerelease: false
6
6
  segments:
7
7
  - 3
8
8
  - 0
9
- - 4
10
- version: 3.0.4
9
+ - 7
10
+ version: 3.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dr Nic Williams
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-11-21 00:00:00 -07:00
19
+ date: 2010-11-29 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -85,6 +85,7 @@ files:
85
85
  - lib/composite_primary_keys/connection_adapters/sqlite3_adapter.rb
86
86
  - lib/composite_primary_keys/finder_methods.rb
87
87
  - lib/composite_primary_keys/fixtures.rb
88
+ - lib/composite_primary_keys/primary_key.rb
88
89
  - lib/composite_primary_keys/query_methods.rb
89
90
  - lib/composite_primary_keys/read.rb
90
91
  - lib/composite_primary_keys/reflection.rb