composite_primary_keys 14.0.5 → 14.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +21 -0
  3. data/Rakefile +1 -1
  4. data/lib/composite_primary_keys/associations/association.rb +2 -2
  5. data/lib/composite_primary_keys/associations/association_scope.rb +1 -1
  6. data/lib/composite_primary_keys/associations/has_many_through_association.rb +19 -0
  7. data/lib/composite_primary_keys/associations/preloader/association.rb +0 -16
  8. data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +1 -2
  9. data/lib/composite_primary_keys/relation/query_methods.rb +14 -16
  10. data/lib/composite_primary_keys/relation.rb +4 -2
  11. data/lib/composite_primary_keys/version.rb +1 -1
  12. data/lib/composite_primary_keys.rb +117 -119
  13. data/scripts/console.rb +2 -2
  14. data/tasks/databases/trilogy.rake +23 -0
  15. data/test/abstract_unit.rb +124 -118
  16. data/test/connections/databases.ci.yml +10 -0
  17. data/test/fixtures/admin.rb +4 -0
  18. data/test/fixtures/comments.yml +6 -0
  19. data/test/fixtures/db_definitions/db2-create-tables.sql +34 -0
  20. data/test/fixtures/db_definitions/db2-drop-tables.sql +7 -1
  21. data/test/fixtures/db_definitions/mysql.sql +23 -0
  22. data/test/fixtures/db_definitions/oracle.drop.sql +4 -0
  23. data/test/fixtures/db_definitions/oracle.sql +21 -0
  24. data/test/fixtures/db_definitions/postgresql.sql +23 -0
  25. data/test/fixtures/db_definitions/sqlite.sql +21 -0
  26. data/test/fixtures/db_definitions/sqlserver.sql +23 -0
  27. data/test/fixtures/moderator.rb +4 -0
  28. data/test/fixtures/room.rb +4 -1
  29. data/test/fixtures/staff_room.rb +6 -0
  30. data/test/fixtures/staff_room_key.rb +6 -0
  31. data/test/fixtures/user.rb +3 -0
  32. data/test/fixtures/user_with_polymorphic_name.rb +9 -0
  33. data/test/test_associations.rb +403 -403
  34. data/test/test_has_one_through.rb +30 -0
  35. data/test/test_polymorphic.rb +6 -0
  36. metadata +11 -4
  37. data/lib/composite_primary_keys/associations/through_association.rb +0 -24
@@ -1,118 +1,124 @@
1
- spec_name = ENV['ADAPTER'] || 'postgresql'
2
- require 'bundler'
3
- require 'minitest/autorun'
4
-
5
- Bundler.setup(:default, spec_name.to_sym)
6
- Bundler.require(:default, spec_name.to_sym)
7
- require 'composite_primary_keys'
8
-
9
- # Require the connection spec
10
- PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
11
- require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
12
-
13
- spec = CompositePrimaryKeys::ConnectionSpec[spec_name]
14
- puts "Loaded #{spec_name}"
15
-
16
- # And now connect to the database
17
- ActiveRecord::Base.establish_connection(spec)
18
-
19
- # Tell active record about the configuration
20
- ActiveRecord::Base.configurations = {test: spec}
21
-
22
- # Tell ActiveRecord where to find models
23
- ActiveSupport::Dependencies.autoload_paths << File.join(PROJECT_ROOT, 'test', 'fixtures')
24
- Dir[File.join(PROJECT_ROOT, 'test', 'fixtures', '*.rb')].each do |file_path|
25
- require_file = file_path.sub(PROJECT_ROOT, '..').sub('.rb', '')
26
- require_relative require_file
27
- end
28
-
29
- I18n.config.enforce_available_locales = true
30
-
31
- class ActiveSupport::TestCase
32
- include ActiveRecord::TestFixtures
33
-
34
- self.fixture_path = File.dirname(__FILE__) + '/fixtures/'
35
- self.use_instantiated_fixtures = false
36
- self.use_transactional_tests = true
37
- self.test_order = :random
38
-
39
- def assert_date_from_db(expected, actual, message = nil)
40
- # SQL Server doesn't have a separate column type just for dates,
41
- # so the time is in the string and incorrectly formatted
42
- if current_adapter?(:SQLServerAdapter)
43
- assert_equal expected.strftime('%Y/%m/%d 00:00:00'), actual.strftime('%Y/%m/%d 00:00:00')
44
- elsif current_adapter?(:SybaseAdapter)
45
- assert_equal expected.to_s, actual.to_date.to_s, message
46
- else
47
- assert_equal expected.to_s, actual.to_s, message
48
- end
49
- end
50
-
51
- def assert_queries(num = 1)
52
- ActiveRecord::Base.connection.class.class_eval do
53
- self.query_count = 0
54
- alias_method :execute, :execute_with_query_counting
55
- end
56
- yield
57
- ensure
58
- ActiveRecord::Base.connection.class.class_eval do
59
- alias_method :execute, :execute_without_query_counting
60
- end
61
- assert_equal num, ActiveRecord::Base.connection.query_count, '#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed.'
62
- end
63
-
64
- def assert_no_queries(&block)
65
- assert_queries(0, &block)
66
- end
67
-
68
- cattr_accessor :classes
69
-
70
- protected
71
-
72
- def testing_with(&block)
73
- classes.keys.each do |key_test|
74
- @key_test = key_test
75
- @klass_info = classes[@key_test]
76
- @klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
77
- order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
78
- @first = @klass.order(order).first
79
- yield
80
- end
81
- end
82
-
83
- def first_id
84
- ids = (1..@primary_keys.length).map {|num| 1}
85
- composite? ? ids.to_composite_ids : ids.first
86
- end
87
-
88
- def composite?
89
- @key_test != :single
90
- end
91
-
92
- # Oracle metadata is in all caps.
93
- def with_quoted_identifiers(s)
94
- s.gsub(/'(\w+)'/) { |m|
95
- if ActiveRecord::Base.configurations[:test]['adapter'] =~ /oracle/i
96
- m.upcase
97
- else
98
- m
99
- end
100
- }
101
- end
102
- end
103
-
104
- def current_adapter?(type)
105
- ActiveRecord::ConnectionAdapters.const_defined?(type) &&
106
- ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
107
- end
108
-
109
- ActiveRecord::Base.connection.class.class_eval do
110
- cattr_accessor :query_count
111
- alias_method :execute_without_query_counting, :execute
112
- def execute_with_query_counting(sql, name = nil)
113
- self.query_count += 1
114
- execute_without_query_counting(sql, name)
115
- end
116
- end
117
-
118
- ActiveRecord::Base.logger = Logger.new(ENV['CPK_LOGFILE'] || STDOUT)
1
+ spec_name = ENV['ADAPTER'] || 'postgresql'
2
+ require 'bundler'
3
+ require 'minitest/autorun'
4
+
5
+ Bundler.setup(:default, spec_name.to_sym)
6
+ Bundler.require(:default, spec_name.to_sym)
7
+ require 'composite_primary_keys'
8
+
9
+ # Require the connection spec
10
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
11
+ require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
12
+
13
+ spec = CompositePrimaryKeys::ConnectionSpec[spec_name]
14
+ puts "Loaded #{spec_name}"
15
+
16
+ # And now connect to the database
17
+ if spec_name == "trilogy"
18
+ require "activerecord-trilogy-adapter"
19
+ require "trilogy_adapter/connection"
20
+ ActiveRecord::Base.extend TrilogyAdapter::Connection
21
+ end
22
+
23
+ ActiveRecord::Base.establish_connection(spec)
24
+
25
+ # Tell active record about the configuration
26
+ ActiveRecord::Base.configurations = {test: spec}
27
+
28
+ # Tell ActiveRecord where to find models
29
+ ActiveSupport::Dependencies.autoload_paths << File.join(PROJECT_ROOT, 'test', 'fixtures')
30
+ Dir[File.join(PROJECT_ROOT, 'test', 'fixtures', '*.rb')].each do |file_path|
31
+ require_file = file_path.sub(PROJECT_ROOT, '..').sub('.rb', '')
32
+ require_relative require_file
33
+ end
34
+
35
+ I18n.config.enforce_available_locales = true
36
+
37
+ class ActiveSupport::TestCase
38
+ include ActiveRecord::TestFixtures
39
+
40
+ self.fixture_path = File.dirname(__FILE__) + '/fixtures/'
41
+ self.use_instantiated_fixtures = false
42
+ self.use_transactional_tests = true
43
+ self.test_order = :random
44
+
45
+ def assert_date_from_db(expected, actual, message = nil)
46
+ # SQL Server doesn't have a separate column type just for dates,
47
+ # so the time is in the string and incorrectly formatted
48
+ if current_adapter?(:SQLServerAdapter)
49
+ assert_equal expected.strftime('%Y/%m/%d 00:00:00'), actual.strftime('%Y/%m/%d 00:00:00')
50
+ elsif current_adapter?(:SybaseAdapter)
51
+ assert_equal expected.to_s, actual.to_date.to_s, message
52
+ else
53
+ assert_equal expected.to_s, actual.to_s, message
54
+ end
55
+ end
56
+
57
+ def assert_queries(num = 1)
58
+ ActiveRecord::Base.connection.class.class_eval do
59
+ self.query_count = 0
60
+ alias_method :execute, :execute_with_query_counting
61
+ end
62
+ yield
63
+ ensure
64
+ ActiveRecord::Base.connection.class.class_eval do
65
+ alias_method :execute, :execute_without_query_counting
66
+ end
67
+ assert_equal num, ActiveRecord::Base.connection.query_count, '#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed.'
68
+ end
69
+
70
+ def assert_no_queries(&block)
71
+ assert_queries(0, &block)
72
+ end
73
+
74
+ cattr_accessor :classes
75
+
76
+ protected
77
+
78
+ def testing_with(&block)
79
+ classes.keys.each do |key_test|
80
+ @key_test = key_test
81
+ @klass_info = classes[@key_test]
82
+ @klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
83
+ order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
84
+ @first = @klass.order(order).first
85
+ yield
86
+ end
87
+ end
88
+
89
+ def first_id
90
+ ids = (1..@primary_keys.length).map {|num| 1}
91
+ composite? ? ids.to_composite_ids : ids.first
92
+ end
93
+
94
+ def composite?
95
+ @key_test != :single
96
+ end
97
+
98
+ # Oracle metadata is in all caps.
99
+ def with_quoted_identifiers(s)
100
+ s.gsub(/'(\w+)'/) { |m|
101
+ if ActiveRecord::Base.configurations[:test]['adapter'] =~ /oracle/i
102
+ m.upcase
103
+ else
104
+ m
105
+ end
106
+ }
107
+ end
108
+ end
109
+
110
+ def current_adapter?(type)
111
+ ActiveRecord::ConnectionAdapters.const_defined?(type) &&
112
+ ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
113
+ end
114
+
115
+ ActiveRecord::Base.connection.class.class_eval do
116
+ cattr_accessor :query_count
117
+ alias_method :execute_without_query_counting, :execute
118
+ def execute_with_query_counting(sql, name = nil)
119
+ self.query_count += 1
120
+ execute_without_query_counting(sql, name)
121
+ end
122
+ end
123
+
124
+ ActiveRecord::Base.logger = Logger.new(ENV['CPK_LOGFILE'] || STDOUT)
@@ -20,3 +20,13 @@ sqlite:
20
20
  adapter: sqlite3
21
21
  database: <%= File.join(project_root, 'db', 'composite_primary_keys_unittest.sqlite') %>
22
22
 
23
+ trilogy:
24
+ adapter: trilogy
25
+ username: github
26
+ password: github
27
+ host: 127.0.0.1
28
+ port: 3306
29
+ encoding: utf8mb4
30
+ charset: utf8mb4
31
+ collation: utf8mb4_bin
32
+ database: composite_primary_keys_unittest
@@ -0,0 +1,4 @@
1
+ class Admin < ActiveRecord::Base
2
+ belongs_to :moderator, :foreign_key => :id, :inverse_of => :admin
3
+ has_one :user, :through => :moderator
4
+ end
@@ -15,3 +15,9 @@ user_comment_2:
15
15
  article: second
16
16
  person_id: 2
17
17
  person_type: User
18
+
19
+ user_comment_3:
20
+ id: 4
21
+ article: first
22
+ person_id: 1
23
+ person_type: User1
@@ -56,6 +56,16 @@ CREATE TABLE users (
56
56
  PRIMARY KEY (id)
57
57
  );
58
58
 
59
+ CREATE TABLE moderators (
60
+ id integer NOT NULL,
61
+ PRIMARY KEY (id)
62
+ );
63
+
64
+ CREATE TABLE admins (
65
+ id integer NOT NULL,
66
+ PRIMARY KEY (id)
67
+ );
68
+
59
69
  CREATE TABLE articles (
60
70
  id integer NOT NULL ,
61
71
  name varchar(50) NOT NULL,
@@ -110,3 +120,27 @@ create table products_restaurants (
110
120
  franchise_id integer not null,
111
121
  store_id integer not null
112
122
  );
123
+
124
+ create table dorms (
125
+ id integer not null,
126
+ primary key (id)
127
+ )
128
+
129
+ create table rooms (
130
+ dorm_id integer not null,
131
+ room_id integer not null,
132
+ primary key (dorm_id, room_id)
133
+ );
134
+
135
+ create table staff_rooms (
136
+ dorm_id integer not null,
137
+ room_id integer not null,
138
+ primary key (dorm_id, room_id)
139
+ );
140
+
141
+ create table staff_room_keys (
142
+ dorm_id integer not null,
143
+ room_id integer not null,
144
+ key_no varchar(50) not null,
145
+ primary key (dorm_id, room_id)
146
+ );
@@ -9,9 +9,15 @@ drop table REFERENCE_TYPES;
9
9
  drop table STREETS;
10
10
  drop table PRODUCTS;
11
11
  drop table USERS;
12
+ drop table MODERATORS;
13
+ drop table ADMINS;
12
14
  drop table SUBURBS;
13
15
  drop table PRODUCT_TARIFFS;
14
16
  drop table KITCHEN_SINK;
15
17
  drop table RESTAURANTS;
16
18
  drop table RESTAURANTS_SUBURBS;
17
- drop table PRODUCTS_RESTAURANTS;
19
+ drop table PRODUCTS_RESTAURANTS;
20
+ drop table DORMS;
21
+ drop table ROOMS;
22
+ drop table STAFF_ROOMS;
23
+ drop table STAFF_ROOM_KEYS;
@@ -58,6 +58,16 @@ create table users (
58
58
  primary key (id)
59
59
  );
60
60
 
61
+ create table moderators (
62
+ id int not null,
63
+ primary key (id)
64
+ );
65
+
66
+ create table admins (
67
+ id int not null,
68
+ primary key (id)
69
+ );
70
+
61
71
  create table articles (
62
72
  id int not null auto_increment,
63
73
  name varchar(50) not null,
@@ -152,6 +162,19 @@ create table room_attribute_assignments (
152
162
  room_attribute_id int not null
153
163
  );
154
164
 
165
+ create table staff_rooms (
166
+ dorm_id int not null,
167
+ room_id int not null,
168
+ primary key (dorm_id, room_id)
169
+ );
170
+
171
+ create table staff_room_keys (
172
+ dorm_id int not null,
173
+ room_id int not null,
174
+ key_no varchar(50) not null,
175
+ primary key (dorm_id, room_id)
176
+ );
177
+
155
178
  create table students (
156
179
  id int not null auto_increment,
157
180
  primary key(id)
@@ -11,6 +11,8 @@ drop table streets;
11
11
  drop sequence streets_seq;
12
12
  drop table users;
13
13
  drop sequence users_seq;
14
+ drop table moderators;
15
+ drop table admins;
14
16
  drop table articles;
15
17
  drop sequence articles_seq;
16
18
  drop table readings;
@@ -35,6 +37,8 @@ drop table room_attributes;
35
37
  drop sequence room_attributes_seq;
36
38
  drop table room_attribute_assignments;
37
39
  drop table room_assignments;
40
+ drop table staff_rooms;
41
+ drop table staff_room_keys;
38
42
  drop table students;
39
43
  drop sequence students_seq;
40
44
  drop table capitols;
@@ -63,6 +63,14 @@ create table users (
63
63
  name varchar(50) not null
64
64
  );
65
65
 
66
+ create table moderators (
67
+ id number(11) primary key
68
+ );
69
+
70
+ create table admins (
71
+ id number(11) primary key
72
+ );
73
+
66
74
  create sequence articles_seq start with 1000;
67
75
 
68
76
  create table articles (
@@ -169,6 +177,19 @@ create table room_attribute_assignments (
169
177
  room_attribute_id number(11) not null
170
178
  );
171
179
 
180
+ create table staff_rooms (
181
+ dorm_id number(11) not null,
182
+ room_id number(11) not null,
183
+ constraint staff_rooms_pk primary key (dorm_id, room_id)
184
+ );
185
+
186
+ create table staff_room_keys (
187
+ dorm_id number(11) not null,
188
+ room_id number(11) not null,
189
+ key_no varchar(50) not null,
190
+ constraint staff_room_keys_pk primary key (dorm_id, room_id)
191
+ );
192
+
172
193
  create sequence students_seq start with 1000;
173
194
 
174
195
  create table students (
@@ -60,6 +60,16 @@ create table users (
60
60
  primary key (id)
61
61
  );
62
62
 
63
+ create table moderators (
64
+ id serial not null,
65
+ primary key (id)
66
+ );
67
+
68
+ create table admins (
69
+ id serial not null,
70
+ primary key (id)
71
+ );
72
+
63
73
  create table articles (
64
74
  id serial not null,
65
75
  name varchar(50) not null,
@@ -154,6 +164,19 @@ create table room_attribute_assignments (
154
164
  room_attribute_id int not null
155
165
  );
156
166
 
167
+ create table staff_rooms (
168
+ dorm_id int not null,
169
+ room_id int not null,
170
+ primary key (dorm_id, room_id)
171
+ );
172
+
173
+ create table staff_room_keys (
174
+ dorm_id int not null,
175
+ room_id int not null,
176
+ key_no varchar(50) not null,
177
+ primary key (dorm_id, room_id)
178
+ );
179
+
157
180
  create table students (
158
181
  id serial not null,
159
182
  primary key (id)
@@ -56,6 +56,14 @@ create table users (
56
56
  name varchar(50) not null
57
57
  );
58
58
 
59
+ create table moderators (
60
+ id integer not null primary key
61
+ );
62
+
63
+ create table admins (
64
+ id integer not null primary key
65
+ );
66
+
59
67
  create table articles (
60
68
  id integer not null primary key autoincrement,
61
69
  name varchar(50) not null
@@ -142,6 +150,19 @@ create table room_attribute_assignments (
142
150
  room_attribute_id integer not null
143
151
  );
144
152
 
153
+ create table staff_rooms (
154
+ dorm_id integer not null,
155
+ room_id integer not null,
156
+ primary key (dorm_id, room_id)
157
+ );
158
+
159
+ create table staff_room_keys (
160
+ dorm_id integer not null,
161
+ room_id integer not null,
162
+ key_no varchar(50) not null,
163
+ primary key (dorm_id, room_id)
164
+ );
165
+
145
166
  create table students (
146
167
  id integer not null primary key autoincrement
147
168
  );
@@ -58,6 +58,14 @@ CREATE TABLE users (
58
58
  name varchar(50) NOT NULL
59
59
  );
60
60
 
61
+ CREATE TABLE moderators (
62
+ id [int] PRIMARY KEY
63
+ );
64
+
65
+ CREATE TABLE admins (
66
+ id [int] PRIMARY KEY
67
+ );
68
+
61
69
  CREATE TABLE articles (
62
70
  id [int] IDENTITY(1000,1) NOT NULL,
63
71
  name varchar(50) NOT NULL
@@ -148,6 +156,21 @@ CREATE TABLE room_attribute_assignments (
148
156
  room_attribute_id [int] NOT NULL
149
157
  );
150
158
 
159
+ CREATE TABLE staff_rooms (
160
+ dorm_id [int] NOT NULL,
161
+ room_id [int] NOT NULL,
162
+ CONSTRAINT [staff_rooms_pk] PRIMARY KEY CLUSTERED
163
+ ( [dorm_id], [room_id] )
164
+ );
165
+
166
+ CREATE TABLE staff_room_keys (
167
+ dorm_id [int] NOT NULL,
168
+ room_id [int] NOT NULL,
169
+ key_no [varchar](50) NOT NULL,
170
+ CONSTRAINT [staff_room_keys_pk] PRIMARY KEY CLUSTERED
171
+ ( [dorm_id], [room_id] )
172
+ );
173
+
151
174
  CREATE TABLE students (
152
175
  id [int] IDENTITY(1000,1) PRIMARY KEY NOT NULL
153
176
  );
@@ -0,0 +1,4 @@
1
+ class Moderator < ActiveRecord::Base
2
+ belongs_to :user, :foreign_key => :id, :inverse_of => :moderator
3
+ has_one :admin, :foreign_key => :id, :inverse_of => :moderator
4
+ end
@@ -4,7 +4,10 @@ class Room < ActiveRecord::Base
4
4
  has_many :room_assignments, :foreign_key => [:dorm_id, :room_id]
5
5
  has_many :room_attribute_assignments, :foreign_key => [:dorm_id, :room_id]
6
6
  has_many :room_attributes, :through => :room_attribute_assignments
7
-
7
+
8
+ has_one :staff_room, :foreign_key => [:dorm_id, :room_id], :inverse_of => :room
9
+ delegate :staff_room_key, :to => :staff_room, :allow_nil => true
10
+
8
11
  def find_custom_room_attributes
9
12
  room_attributes.where("room_attributes.name != ?", "type")
10
13
  end
@@ -0,0 +1,6 @@
1
+ class StaffRoom < ActiveRecord::Base
2
+ self.primary_keys = :dorm_id, :room_id
3
+
4
+ belongs_to :room, :foreign_key => [:dorm_id, :room_id], :inverse_of => :staff_room
5
+ has_one :staff_room_key, :foreign_key => [:dorm_id, :room_id], :inverse_of => :staff_room
6
+ end
@@ -0,0 +1,6 @@
1
+ class StaffRoomKey < ActiveRecord::Base
2
+ self.primary_keys = :dorm_id, :room_id
3
+
4
+ belongs_to :staff_room, :foreign_key => [:dorm_id, :room_id], :inverse_of => :staff_room_key
5
+ has_one :room, :through => :staff_room
6
+ end
@@ -5,6 +5,9 @@ class User < ActiveRecord::Base
5
5
  has_many :comments, :as => :person
6
6
  has_one :first_comment, :as => :person, :class_name => "Comment"
7
7
 
8
+ has_one :moderator, :foreign_key => :id, :inverse_of => :user
9
+ delegate :admin, :to => :moderator, :allow_nil => true
10
+
8
11
  def find_custom_articles
9
12
  articles.where("name = ?", "Article One")
10
13
  end
@@ -0,0 +1,9 @@
1
+ class UserWithPolymorphicName < ActiveRecord::Base
2
+ self.table_name = "users"
3
+
4
+ has_many :comments, :as => :person
5
+
6
+ def self.polymorphic_name
7
+ "User1"
8
+ end
9
+ end