composite_primary_keys 0.7.5 → 0.8.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.
Files changed (46) hide show
  1. data/Manifest.txt +75 -0
  2. data/Rakefile +83 -101
  3. data/lib/composite_primary_keys.rb +8 -0
  4. data/lib/composite_primary_keys/associations.rb +66 -18
  5. data/lib/composite_primary_keys/base.rb +169 -159
  6. data/lib/composite_primary_keys/calculations.rb +63 -0
  7. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +11 -0
  8. data/lib/composite_primary_keys/version.rb +2 -2
  9. data/scripts/txt2html +4 -2
  10. data/scripts/txt2js +3 -2
  11. data/test/abstract_unit.rb +9 -2
  12. data/test/connections/native_mysql/connection.rb +5 -2
  13. data/test/connections/native_postgresql/connection.rb +15 -0
  14. data/test/connections/native_sqlite/connection.rb +10 -0
  15. data/test/fixtures/db_definitions/mysql.sql +20 -0
  16. data/test/fixtures/db_definitions/postgresql.sql +100 -0
  17. data/test/fixtures/db_definitions/sqlite.sql +84 -0
  18. data/test/fixtures/group.rb +3 -0
  19. data/test/fixtures/groups.yml +3 -0
  20. data/test/fixtures/membership.rb +7 -0
  21. data/test/fixtures/membership_status.rb +3 -0
  22. data/test/fixtures/membership_statuses.yml +8 -0
  23. data/test/fixtures/memberships.yml +6 -0
  24. data/test/{associations_test.rb → test_associations.rb} +22 -12
  25. data/test/{attributes_test.rb → test_attributes.rb} +4 -5
  26. data/test/{clone_test.rb → test_clone.rb} +2 -3
  27. data/test/{create_test.rb → test_create.rb} +2 -3
  28. data/test/{delete_test.rb → test_delete.rb} +2 -3
  29. data/test/{dummy_test.rb → test_dummy.rb} +4 -5
  30. data/test/{find_test.rb → test_find.rb} +3 -4
  31. data/test/{ids_test.rb → test_ids.rb} +4 -4
  32. data/test/{miscellaneous_test.rb → test_miscellaneous.rb} +2 -3
  33. data/test/{pagination_test.rb → test_pagination.rb} +4 -3
  34. data/test/{santiago_test.rb → test_santiago.rb} +5 -3
  35. data/test/test_tutorial_examle.rb +29 -0
  36. data/test/{update_test.rb → test_update.rb} +2 -3
  37. data/website/index.html +267 -201
  38. data/website/index.txt +74 -70
  39. data/website/stylesheets/screen.css +33 -3
  40. data/website/version-raw.js +1 -1
  41. data/website/version.js +1 -1
  42. metadata +80 -66
  43. data/scripts/http-access2-2.0.6.gem +0 -0
  44. data/scripts/rubyforge +0 -217
  45. data/scripts/rubyforge-orig +0 -217
  46. data/test/fixtures/db_definitions/mysql.drop.sql +0 -10
@@ -1,8 +1,8 @@
1
1
  module CompositePrimaryKeys
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 7
5
- TINY = 5
4
+ MINOR = 8
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
3
4
  require 'redcloth'
4
5
  require 'syntax/convertors/html'
5
6
  require 'erb'
6
- require '../lib/composite_primary_keys/version.rb'
7
+ require File.dirname(__FILE__) + '/../lib/composite_primary_keys/version.rb'
7
8
 
8
9
  version = CompositePrimaryKeys::VERSION::STRING
9
10
  download = 'http://rubyforge.org/projects/compositekeys'
@@ -34,7 +35,8 @@ end
34
35
 
35
36
  if ARGV.length >= 1
36
37
  src, template = ARGV
37
- template ||= 'template.rhtml'
38
+ template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
39
+
38
40
  else
39
41
  puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
40
42
  exit!
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
3
4
  require 'redcloth'
4
5
  require 'syntax/convertors/html'
5
6
  require 'erb'
6
7
  require 'active_support'
7
- require '../lib/composite_primary_keys/version.rb'
8
+ require File.dirname(__FILE__) + '/../lib/composite_primary_keys/version.rb'
8
9
 
9
10
  version = CompositePrimaryKeys::VERSION::STRING
10
11
  download = 'http://rubyforge.org/projects/compositekeys'
@@ -35,7 +36,7 @@ end
35
36
 
36
37
  if ARGV.length >= 1
37
38
  src, template = ARGV
38
- template ||= 'template.js'
39
+ template ||= File.dirname(__FILE__) + '/../website/template.js'
39
40
  else
40
41
  puts("Usage: #{File.split($0).last} source.txt [template.js] > output.html")
41
42
  exit!
@@ -1,12 +1,18 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
2
 
3
+ require 'rubygems'
3
4
  require 'test/unit'
4
5
  require 'hash_tricks'
5
6
  require 'active_record'
6
7
  require 'active_record/fixtures'
7
8
  require 'active_support/binding_of_caller'
8
9
  require 'active_support/breakpoint'
9
- require 'connection'
10
+ begin
11
+ require 'connection'
12
+ rescue MissingSourceFile => e
13
+ adapter = 'postgresql' #'sqlite'
14
+ require "#{File.dirname(__FILE__)}/connections/native_#{adapter}/connection"
15
+ end
10
16
  require 'composite_primary_keys'
11
17
 
12
18
  QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
@@ -56,7 +62,8 @@ protected
56
62
  classes.keys.each do |@key_test|
57
63
  @klass_info = classes[@key_test]
58
64
  @klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
59
- @first = @klass.find_first
65
+ order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
66
+ @first = @klass.find(:first, :order => order)
60
67
  yield
61
68
  end
62
69
  end
@@ -5,9 +5,12 @@ ActiveRecord::Base.logger = Logger.new("debug.log")
5
5
 
6
6
  db1 = 'composite_primary_keys_unittest'
7
7
 
8
- ActiveRecord::Base.establish_connection(
8
+ connection_options = {
9
9
  :adapter => "mysql",
10
10
  :username => "root",
11
11
  :encoding => "utf8",
12
12
  :database => db1
13
- )
13
+ }
14
+
15
+ ActiveRecord::Base.configurations = { db1 => connection_options }
16
+ ActiveRecord::Base.establish_connection(connection_options)
@@ -0,0 +1,15 @@
1
+ print "Using native Postgresql\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = 'composite_primary_keys_unittest'
7
+
8
+ connection_options = {
9
+ :adapter => "postgresql",
10
+ :encoding => "utf8",
11
+ :database => db1
12
+ }
13
+
14
+ ActiveRecord::Base.configurations = { db1 => connection_options }
15
+ ActiveRecord::Base.establish_connection(connection_options)
@@ -0,0 +1,10 @@
1
+ print "Using native Sqlite3\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ ActiveRecord::Base.establish_connection(
7
+ :adapter => "sqlite3",
8
+ :dbfile => "test.db"
9
+ )
10
+
@@ -70,3 +70,23 @@ CREATE TABLE `readings` (
70
70
  PRIMARY KEY (`id`)
71
71
  ) TYPE=InnoDB;
72
72
 
73
+ CREATE TABLE groups (
74
+ id int(11) NOT NULL auto_increment,
75
+ name varchar(50) NOT NULL,
76
+ PRIMARY KEY (id)
77
+ ) TYPE=InnoDB;
78
+
79
+ CREATE TABLE memberships (
80
+ user_id int(11) NOT NULL,
81
+ group_id int(11) NOT NULL,
82
+ PRIMARY KEY (user_id,group_id)
83
+ ) TYPE=InnoDB;
84
+
85
+ CREATE TABLE membership_statuses (
86
+ id int(11) NOT NULL auto_increment,
87
+ user_id int(11) NOT NULL,
88
+ group_id int(11) NOT NULL,
89
+ status varchar(50) NOT NULL,
90
+ PRIMARY KEY (id)
91
+ ) TYPE=InnoDB;
92
+
@@ -0,0 +1,100 @@
1
+ CREATE SEQUENCE public.reference_types_seq START 100;
2
+ CREATE TABLE reference_types (
3
+ reference_type_id int DEFAULT nextval('public.reference_types_seq'),
4
+ type_label varchar(50) default NULL,
5
+ abbreviation varchar(50) default NULL,
6
+ description varchar(50) default NULL,
7
+ PRIMARY KEY (reference_type_id)
8
+ );
9
+
10
+ CREATE TABLE reference_codes (
11
+ reference_type_id int NOT NULL,
12
+ reference_code int NOT NULL,
13
+ code_label varchar(50) default NULL,
14
+ abbreviation varchar(50) default NULL,
15
+ description varchar(50) default NULL,
16
+ PRIMARY KEY (reference_type_id,reference_code)
17
+ );
18
+
19
+ CREATE SEQUENCE public.products_seq START 100;
20
+ CREATE TABLE products (
21
+ id int NOT NULL DEFAULT nextval('public.products_seq'),
22
+ name varchar(50) default NULL,
23
+ PRIMARY KEY (id)
24
+ );
25
+
26
+ CREATE TABLE tariffs (
27
+ tariff_id int NOT NULL,
28
+ start_date date NOT NULL,
29
+ amount int default NULL,
30
+ PRIMARY KEY (tariff_id,start_date)
31
+ );
32
+
33
+ CREATE TABLE product_tariffs (
34
+ product_id int NOT NULL,
35
+ tariff_id int NOT NULL,
36
+ tariff_start_date date NOT NULL,
37
+ PRIMARY KEY (product_id,tariff_id,tariff_start_date)
38
+ );
39
+
40
+ CREATE TABLE suburbs (
41
+ city_id int NOT NULL,
42
+ suburb_id int NOT NULL,
43
+ name varchar(50) NOT NULL,
44
+ PRIMARY KEY (city_id,suburb_id)
45
+ );
46
+
47
+ CREATE SEQUENCE public.streets_seq START 100;
48
+ CREATE TABLE streets (
49
+ id int NOT NULL DEFAULT nextval('public.streets_seq'),
50
+ city_id int NOT NULL,
51
+ suburb_id int NOT NULL,
52
+ name varchar(50) NOT NULL,
53
+ PRIMARY KEY (id)
54
+ );
55
+
56
+ CREATE SEQUENCE public.users_seq START 100;
57
+ CREATE TABLE users (
58
+ id int NOT NULL DEFAULT nextval('public.users_seq'),
59
+ name varchar(50) NOT NULL,
60
+ PRIMARY KEY (id)
61
+ );
62
+
63
+ CREATE SEQUENCE public.articles_seq START 100;
64
+ CREATE TABLE articles (
65
+ id int NOT NULL DEFAULT nextval('public.articles_seq'),
66
+ name varchar(50) NOT NULL,
67
+ PRIMARY KEY (id)
68
+ );
69
+
70
+ CREATE SEQUENCE public.readings_seq START 100;
71
+ CREATE TABLE readings (
72
+ id int NOT NULL DEFAULT nextval('public.readings_seq'),
73
+ user_id int NOT NULL,
74
+ article_id int NOT NULL,
75
+ rating int NOT NULL,
76
+ PRIMARY KEY (id)
77
+ );
78
+
79
+ CREATE SEQUENCE public.groups_seq START 100;
80
+ CREATE TABLE groups (
81
+ id int NOT NULL DEFAULT nextval('public.groups_seq'),
82
+ name varchar(50) NOT NULL,
83
+ PRIMARY KEY (id)
84
+ );
85
+
86
+ CREATE TABLE memberships (
87
+ user_id int NOT NULL,
88
+ group_id int NOT NULL,
89
+ PRIMARY KEY (user_id,group_id)
90
+ );
91
+
92
+ CREATE SEQUENCE public.membership_statuses_seq START 100;
93
+ CREATE TABLE membership_statuses (
94
+ id int NOT NULL DEFAULT nextval('public.membership_statuses_seq'),
95
+ user_id int NOT NULL,
96
+ group_id int NOT NULL,
97
+ status varchar(50) NOT NULL,
98
+ PRIMARY KEY (id)
99
+ );
100
+
@@ -0,0 +1,84 @@
1
+ CREATE TABLE `reference_types` (
2
+ `reference_type_id` INTEGER PRIMARY KEY,
3
+ `type_label` varchar(50) default NULL,
4
+ `abbreviation` varchar(50) default NULL,
5
+ `description` varchar(50) default NULL
6
+ );
7
+
8
+ CREATE TABLE `reference_codes` (
9
+ `reference_type_id` int(11) NOT NULL,
10
+ `reference_code` int(11) NOT NULL,
11
+ `code_label` varchar(50) default NULL,
12
+ `abbreviation` varchar(50) default NULL,
13
+ `description` varchar(50) default NULL,
14
+ PRIMARY KEY (`reference_type_id`,`reference_code`)
15
+ );
16
+
17
+ CREATE TABLE `products` (
18
+ `id` int(11) NOT NULL PRIMARY KEY,
19
+ `name` varchar(50) default NULL
20
+ );
21
+
22
+ CREATE TABLE `tariffs` (
23
+ `tariff_id` int(11) NOT NULL,
24
+ `start_date` date NOT NULL,
25
+ `amount` integer(11) default NULL,
26
+ PRIMARY KEY (`tariff_id`,`start_date`)
27
+ );
28
+
29
+ CREATE TABLE `product_tariffs` (
30
+ `product_id` int(11) NOT NULL,
31
+ `tariff_id` int(11) NOT NULL,
32
+ `tariff_start_date` date NOT NULL,
33
+ PRIMARY KEY (`product_id`,`tariff_id`,`tariff_start_date`)
34
+ );
35
+
36
+ CREATE TABLE `suburbs` (
37
+ `city_id` int(11) NOT NULL,
38
+ `suburb_id` int(11) NOT NULL,
39
+ `name` varchar(50) NOT NULL,
40
+ PRIMARY KEY (`city_id`,`suburb_id`)
41
+ );
42
+
43
+ CREATE TABLE `streets` (
44
+ `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
45
+ `city_id` int(11) NOT NULL,
46
+ `suburb_id` int(11) NOT NULL,
47
+ `name` varchar(50) NOT NULL
48
+ );
49
+
50
+ CREATE TABLE `users` (
51
+ `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
52
+ `name` varchar(50) NOT NULL
53
+ );
54
+
55
+ CREATE TABLE `articles` (
56
+ `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
57
+ `name` varchar(50) NOT NULL
58
+ );
59
+
60
+ CREATE TABLE `readings` (
61
+ `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
62
+ `user_id` int(11) NOT NULL,
63
+ `article_id` int(11) NOT NULL,
64
+ `rating` int(11) NOT NULL
65
+ );
66
+
67
+ CREATE TABLE groups (
68
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
69
+ name varchar(50) NOT NULL
70
+ );
71
+
72
+ CREATE TABLE memberships (
73
+ user_id int NOT NULL,
74
+ group_id int NOT NULL,
75
+ PRIMARY KEY (user_id,group_id)
76
+ );
77
+
78
+ CREATE TABLE membership_statuses (
79
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
80
+ user_id int NOT NULL,
81
+ group_id int NOT NULL,
82
+ status varchar(50) NOT NULL
83
+ );
84
+
@@ -0,0 +1,3 @@
1
+ class Group < ActiveRecord::Base
2
+ has_many :memberships
3
+ end
@@ -0,0 +1,3 @@
1
+ cpk:
2
+ id: 1
3
+ name: Composite Primary Keys
@@ -0,0 +1,7 @@
1
+ class Membership < ActiveRecord::Base
2
+ # set_primary_keys *keys - turns on composite key functionality
3
+ set_primary_keys :user_id, :group_id
4
+ belongs_to :user
5
+ belongs_to :group
6
+ has_many :statuses, :class_name => 'MembershipStatus', :foreign_key => [:user_id, :group_id]
7
+ end
@@ -0,0 +1,3 @@
1
+ class MembershipStatus < ActiveRecord::Base
2
+ belongs_to :membership, :foreign_key => [:user_id, :group_id]
3
+ end
@@ -0,0 +1,8 @@
1
+ santiago-cpk:
2
+ user_id: 1
3
+ group_id: 1
4
+ status: Active
5
+ drnic-cpk:
6
+ user_id: 2
7
+ group_id: 1
8
+ status: Owner
@@ -0,0 +1,6 @@
1
+ santiago-cpk:
2
+ user_id: 1
3
+ group_id: 1
4
+ drnic-cpk:
5
+ user_id: 2
6
+ group_id: 1
@@ -5,15 +5,14 @@ require 'fixtures/product_tariff'
5
5
  require 'fixtures/suburb'
6
6
  require 'fixtures/street'
7
7
 
8
- class AssociationTest < Test::Unit::TestCase
9
- fixtures :products, :tariffs, :product_tariffs, :suburbs, :streets
8
+ class TestAssociations < Test::Unit::TestCase
10
9
 
11
10
  def setup
12
- super
13
- @first_product = products(:first_product)
14
- @flat = tariffs(:flat)
15
- @free = tariffs(:free)
16
- @first_flat = product_tariffs(:first_flat)
11
+ create_fixtures :products, :tariffs, :product_tariffs, :suburbs, :streets
12
+ @first_product = Product.find(1)
13
+ @flat = Tariff.find(1, Date.today.to_s(:db))
14
+ @free = Tariff.find(2, Date.today.to_s(:db))
15
+ @first_flat = ProductTariff.find(1, 1, Date.today.to_s(:db))
17
16
  end
18
17
 
19
18
  def test_setup
@@ -61,24 +60,35 @@ class AssociationTest < Test::Unit::TestCase
61
60
  assert @products = Product.find(:all, :include => :product_tariffs)
62
61
  assert_equal 2, @products.length
63
62
  assert_not_nil @products.first.instance_variable_get('@product_tariffs'), '@product_tariffs not set; should be array'
64
- assert_equal 3, @products.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length}, "Incorrect number of product_tariffs returned"
63
+ assert_equal 3, @products.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
64
+ "Incorrect number of product_tariffs returned"
65
65
  end
66
66
 
67
67
  def test_find_includes_tariffs
68
68
  assert @tariffs = Tariff.find(:all, :include => :product_tariffs)
69
69
  assert_equal 3, @tariffs.length
70
70
  assert_not_nil @tariffs.first.instance_variable_get('@product_tariffs'), '@product_tariffs not set; should be array'
71
- assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length}, "Incorrect number of product_tariffs returned"
71
+ assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
72
+ "Incorrect number of product_tariffs returnedturned"
72
73
  end
73
74
 
74
75
  def XXX_test_find_includes_extended
75
76
  # TODO - what's the correct syntax?
76
77
  assert @products = Product.find(:all, :include => {:product_tariffs => :tariffs})
77
- assert_equal 3, @products.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length}, "Incorrect number of product_tariffs returned"
78
+ assert_equal 3, @products.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
79
+ "Incorrect number of product_tariffs returned"
78
80
 
79
81
  assert @tariffs = Tariff.find(:all, :include => {:product_tariffs => :products})
80
- assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length}, "Incorrect number of product_tariffs returned"
81
-
82
+ assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
83
+ "Incorrect number of product_tariffs returned"
84
+ end
85
+
86
+ def test_join_where_clause
87
+ @product = Product.find(:first, :include => :product_tariffs)
88
+ where_clause = @product.product_tariffs.composite_where_clause(
89
+ ['foo','bar'], [1,2]
90
+ )
91
+ assert_equal('(foo=1 AND bar=2)', where_clause)
82
92
  end
83
93
 
84
94
  end
@@ -5,8 +5,7 @@ require 'fixtures/product'
5
5
  require 'fixtures/tariff'
6
6
  require 'fixtures/product_tariff'
7
7
 
8
- class AttributesTest < Test::Unit::TestCase
9
- fixtures :reference_types, :reference_codes, :products, :tariffs, :product_tariffs
8
+ class TestAttributes < Test::Unit::TestCase
10
9
 
11
10
  CLASSES = {
12
11
  :single => {
@@ -20,7 +19,7 @@ class AttributesTest < Test::Unit::TestCase
20
19
  }
21
20
 
22
21
  def setup
23
- super
22
+ create_fixtures :reference_types, :reference_codes, :products, :tariffs, :product_tariffs
24
23
  self.class.classes = CLASSES
25
24
  end
26
25
 
@@ -49,8 +48,8 @@ class AttributesTest < Test::Unit::TestCase
49
48
  end
50
49
 
51
50
  def test_brackets_foreign_key_assignment
52
- @flat = tariffs(:flat)
53
- @second_free = product_tariffs(:second_free)
51
+ @flat = Tariff.find(1, Date.today.to_s(:db))
52
+ @second_free = ProductTariff.find(2,2,Date.today.to_s(:db))
54
53
  @second_free_fk = [:tariff_id, :tariff_start_date]
55
54
  @second_free[key = @second_free_fk] = @flat.id
56
55
  compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)