composite_primary_keys 3.0.4 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
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