composite_primary_keys 0.7.5 → 0.8.0

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