composite_primary_keys 14.0.5 → 14.0.7

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