composite_primary_keys 7.0.16 → 8.0.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.
- checksums.yaml +4 -4
- data/History.rdoc +600 -623
- data/lib/composite_primary_keys.rb +113 -115
- data/lib/composite_primary_keys/associations/association.rb +23 -23
- data/lib/composite_primary_keys/associations/association_scope.rb +73 -77
- data/lib/composite_primary_keys/associations/collection_association.rb +15 -0
- data/lib/composite_primary_keys/associations/has_many_association.rb +69 -56
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +30 -28
- data/lib/composite_primary_keys/associations/join_dependency.rb +87 -89
- data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +22 -22
- data/lib/composite_primary_keys/associations/preloader/association.rb +90 -78
- data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +19 -19
- data/lib/composite_primary_keys/associations/singular_association.rb +15 -0
- data/lib/composite_primary_keys/attribute_methods.rb +9 -0
- data/lib/composite_primary_keys/attribute_methods/dirty.rb +29 -26
- data/lib/composite_primary_keys/attribute_methods/read.rb +19 -34
- data/lib/composite_primary_keys/attribute_methods/write.rb +30 -36
- data/lib/composite_primary_keys/attribute_set/builder.rb +20 -0
- data/lib/composite_primary_keys/base.rb +135 -129
- data/lib/composite_primary_keys/composite_arrays.rb +30 -30
- data/lib/composite_primary_keys/composite_predicates.rb +50 -50
- data/lib/composite_primary_keys/composite_relation.rb +48 -48
- data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +2 -4
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +46 -60
- data/lib/composite_primary_keys/core.rb +69 -47
- data/lib/composite_primary_keys/fixtures.rb +22 -22
- data/lib/composite_primary_keys/persistence.rb +56 -60
- data/lib/composite_primary_keys/relation.rb +68 -56
- data/lib/composite_primary_keys/relation/calculations.rb +79 -75
- data/lib/composite_primary_keys/relation/finder_methods.rb +175 -196
- data/lib/composite_primary_keys/relation/query_methods.rb +40 -40
- data/lib/composite_primary_keys/sanitization.rb +52 -52
- data/lib/composite_primary_keys/validations/uniqueness.rb +36 -37
- data/lib/composite_primary_keys/version.rb +8 -8
- data/tasks/databases/oracle.rake +25 -25
- data/tasks/databases/sqlserver.rake +27 -40
- data/test/abstract_unit.rb +113 -113
- data/test/connections/databases.ci.yml +15 -15
- data/test/connections/databases.example.yml +18 -18
- data/test/connections/native_oracle/connection.rb +11 -11
- data/test/connections/native_oracle_enhanced/connection.rb +16 -16
- data/test/connections/native_sqlserver/connection.rb +11 -14
- data/test/fixtures/comment.rb +7 -7
- data/test/fixtures/db_definitions/db2-create-tables.sql +125 -126
- data/test/fixtures/db_definitions/db2-drop-tables.sql +18 -18
- data/test/fixtures/db_definitions/mysql.sql +207 -208
- data/test/fixtures/db_definitions/oracle.drop.sql +45 -45
- data/test/fixtures/db_definitions/oracle.sql +222 -223
- data/test/fixtures/db_definitions/postgresql.sql +209 -210
- data/test/fixtures/db_definitions/sqlite.sql +196 -197
- data/test/fixtures/db_definitions/sqlserver.drop.sql +91 -94
- data/test/fixtures/db_definitions/sqlserver.sql +225 -232
- data/test/fixtures/dorm.rb +2 -2
- data/test/fixtures/employee.rb +5 -5
- data/test/fixtures/membership.rb +6 -6
- data/test/fixtures/membership_statuses.yml +16 -16
- data/test/fixtures/memberships.yml +10 -10
- data/test/fixtures/product_tariffs.yml +14 -14
- data/test/fixtures/reference_code.rb +7 -7
- data/test/fixtures/restaurants_suburb.rb +2 -2
- data/test/fixtures/suburb.rb +5 -5
- data/test/fixtures/topic.rb +5 -5
- data/test/fixtures/topic_source.rb +6 -6
- data/test/fixtures/topic_sources.yml +3 -3
- data/test/fixtures/topics.yml +8 -8
- data/test/fixtures/users.yml +10 -10
- data/test/test_associations.rb +295 -275
- data/test/test_attribute_methods.rb +63 -63
- data/test/test_attributes.rb +60 -60
- data/test/test_calculations.rb +37 -42
- data/test/test_callbacks.rb +99 -99
- data/test/test_create.rb +112 -112
- data/test/test_delete.rb +148 -152
- data/test/test_delete_all.rb +28 -26
- data/test/test_dumpable.rb +15 -15
- data/test/test_enum.rb +21 -20
- data/test/test_equal.rb +26 -26
- data/test/test_find.rb +118 -118
- data/test/test_habtm.rb +113 -113
- data/test/test_nested_attributes.rb +124 -124
- data/test/test_polymorphic.rb +26 -26
- data/test/test_predicates.rb +40 -40
- data/test/test_santiago.rb +23 -23
- data/test/test_suite.rb +33 -34
- data/test/test_touch.rb +23 -23
- data/test/test_tutorial_example.rb +21 -21
- data/test/test_update.rb +71 -71
- metadata +9 -13
- data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -20
- data/lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb +0 -59
- data/lib/composite_primary_keys/associations/join_dependency/join_part.rb +0 -39
- data/lib/composite_primary_keys/associations/preloader/has_and_belongs_to_many.rb +0 -46
- data/lib/composite_primary_keys/connection_adapters/sqlserver_adapter.rb +0 -17
- data/lib/composite_primary_keys/locking/optimistic.rb +0 -55
- data/test/test_optimistic.rb +0 -18
@@ -1,41 +1,41 @@
|
|
1
|
-
module CompositePrimaryKeys::ActiveRecord::QueryMethods
|
2
|
-
|
3
|
-
def reverse_sql_order(order_query)
|
4
|
-
# CPK
|
5
|
-
# order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
|
6
|
-
|
7
|
-
# break apart CPKs
|
8
|
-
order_query = primary_key.map do |key|
|
9
|
-
"#{quoted_table_name}.#{connection.quote_column_name(key)} ASC"
|
10
|
-
end if order_query.empty?
|
11
|
-
|
12
|
-
order_query.map do |o|
|
13
|
-
case o
|
14
|
-
when Arel::Nodes::Ordering
|
15
|
-
o.reverse
|
16
|
-
when String, Symbol
|
17
|
-
o.to_s.split(',').collect do |s|
|
18
|
-
s.strip!
|
19
|
-
s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
|
20
|
-
end
|
21
|
-
else
|
22
|
-
o
|
23
|
-
end
|
24
|
-
end.flatten
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
def order(*args)
|
29
|
-
args.map! do |arg|
|
30
|
-
if arg.is_a?(Arel::Nodes::Ordering) && arg.expr.name.is_a?(Array)
|
31
|
-
arg = arg.expr.name.map do |key|
|
32
|
-
cloned_node = arg.clone
|
33
|
-
cloned_node.expr.name = key
|
34
|
-
cloned_node
|
35
|
-
end
|
36
|
-
end
|
37
|
-
arg
|
38
|
-
end if composite?
|
39
|
-
super(*args)
|
40
|
-
end
|
1
|
+
module CompositePrimaryKeys::ActiveRecord::QueryMethods
|
2
|
+
|
3
|
+
def reverse_sql_order(order_query)
|
4
|
+
# CPK
|
5
|
+
# order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
|
6
|
+
|
7
|
+
# break apart CPKs
|
8
|
+
order_query = primary_key.map do |key|
|
9
|
+
"#{quoted_table_name}.#{connection.quote_column_name(key)} ASC"
|
10
|
+
end if order_query.empty?
|
11
|
+
|
12
|
+
order_query.map do |o|
|
13
|
+
case o
|
14
|
+
when Arel::Nodes::Ordering
|
15
|
+
o.reverse
|
16
|
+
when String, Symbol
|
17
|
+
o.to_s.split(',').collect do |s|
|
18
|
+
s.strip!
|
19
|
+
s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
|
20
|
+
end
|
21
|
+
else
|
22
|
+
o
|
23
|
+
end
|
24
|
+
end.flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def order(*args)
|
29
|
+
args.map! do |arg|
|
30
|
+
if arg.is_a?(Arel::Nodes::Ordering) && arg.expr.name.is_a?(Array)
|
31
|
+
arg = arg.expr.name.map do |key|
|
32
|
+
cloned_node = arg.clone
|
33
|
+
cloned_node.expr.name = key
|
34
|
+
cloned_node
|
35
|
+
end
|
36
|
+
end
|
37
|
+
arg
|
38
|
+
end if composite?
|
39
|
+
super(*args)
|
40
|
+
end
|
41
41
|
end
|
@@ -1,52 +1,52 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Sanitization
|
3
|
-
module ClassMethods
|
4
|
-
protected
|
5
|
-
# Accepts a hash of SQL conditions and replaces those attributes
|
6
|
-
# that correspond to a +composed_of+ relationship with their expanded
|
7
|
-
# aggregate attribute values.
|
8
|
-
# Given:
|
9
|
-
# class Person < ActiveRecord::Base
|
10
|
-
# composed_of :address, class_name: "Address",
|
11
|
-
# mapping: [%w(address_street street), %w(address_city city)]
|
12
|
-
# end
|
13
|
-
# Then:
|
14
|
-
# { address: Address.new("813 abc st.", "chicago") }
|
15
|
-
# # => { address_street: "813 abc st.", address_city: "chicago" }
|
16
|
-
def expand_hash_conditions_for_aggregates(attrs)
|
17
|
-
expanded_attrs = {}
|
18
|
-
attrs.each do |attr, value|
|
19
|
-
if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
|
20
|
-
attr.each_with_index do |key,i|
|
21
|
-
expanded_attrs[key] = value.flatten[i]
|
22
|
-
end
|
23
|
-
elsif aggregation = reflect_on_aggregation(attr.to_sym)
|
24
|
-
mapping = aggregation.mapping
|
25
|
-
mapping.each do |field_attr, aggregate_attr|
|
26
|
-
if mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
27
|
-
expanded_attrs[field_attr] = value
|
28
|
-
else
|
29
|
-
expanded_attrs[field_attr] = value.send(aggregate_attr)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
else
|
33
|
-
expanded_attrs[attr] = value
|
34
|
-
end
|
35
|
-
end
|
36
|
-
expanded_attrs
|
37
|
-
end
|
38
|
-
|
39
|
-
def quoted_id
|
40
|
-
# CPK
|
41
|
-
#quote_value(id, column_for_attribute(self.class.primary_key))
|
42
|
-
if self.composite?
|
43
|
-
[self.class.primary_keys, ids].
|
44
|
-
transpose.
|
45
|
-
map {|attr_name,id| quote_value(id, column_for_attribute(attr_name))}
|
46
|
-
else
|
47
|
-
quote_value(id, column_for_attribute(self.class.primary_key))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Sanitization
|
3
|
+
module ClassMethods
|
4
|
+
protected
|
5
|
+
# Accepts a hash of SQL conditions and replaces those attributes
|
6
|
+
# that correspond to a +composed_of+ relationship with their expanded
|
7
|
+
# aggregate attribute values.
|
8
|
+
# Given:
|
9
|
+
# class Person < ActiveRecord::Base
|
10
|
+
# composed_of :address, class_name: "Address",
|
11
|
+
# mapping: [%w(address_street street), %w(address_city city)]
|
12
|
+
# end
|
13
|
+
# Then:
|
14
|
+
# { address: Address.new("813 abc st.", "chicago") }
|
15
|
+
# # => { address_street: "813 abc st.", address_city: "chicago" }
|
16
|
+
def expand_hash_conditions_for_aggregates(attrs)
|
17
|
+
expanded_attrs = {}
|
18
|
+
attrs.each do |attr, value|
|
19
|
+
if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
|
20
|
+
attr.each_with_index do |key,i|
|
21
|
+
expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
|
22
|
+
end
|
23
|
+
elsif aggregation = reflect_on_aggregation(attr.to_sym)
|
24
|
+
mapping = aggregation.mapping
|
25
|
+
mapping.each do |field_attr, aggregate_attr|
|
26
|
+
if mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
27
|
+
expanded_attrs[field_attr] = value
|
28
|
+
else
|
29
|
+
expanded_attrs[field_attr] = value.send(aggregate_attr)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
expanded_attrs[attr] = value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
expanded_attrs
|
37
|
+
end
|
38
|
+
|
39
|
+
def quoted_id
|
40
|
+
# CPK
|
41
|
+
#quote_value(id, column_for_attribute(self.class.primary_key))
|
42
|
+
if self.composite?
|
43
|
+
[self.class.primary_keys, ids].
|
44
|
+
transpose.
|
45
|
+
map {|attr_name,id| quote_value(id, column_for_attribute(attr_name))}
|
46
|
+
else
|
47
|
+
quote_value(id, column_for_attribute(self.class.primary_key))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,38 +1,37 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Validations
|
3
|
-
class UniquenessValidator
|
4
|
-
def validate_each(record, attribute, value)
|
5
|
-
finder_class = find_finder_class_for(record)
|
6
|
-
table = finder_class.arel_table
|
7
|
-
value = map_enum_attribute(finder_class,attribute,value)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
relation =
|
26
|
-
relation =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
error_options =
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Validations
|
3
|
+
class UniquenessValidator
|
4
|
+
def validate_each(record, attribute, value)
|
5
|
+
finder_class = find_finder_class_for(record)
|
6
|
+
table = finder_class.arel_table
|
7
|
+
value = map_enum_attribute(finder_class, attribute, value)
|
8
|
+
|
9
|
+
relation = build_relation(finder_class, table, attribute, value)
|
10
|
+
# CPK
|
11
|
+
# relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
|
12
|
+
if record.persisted?
|
13
|
+
not_eq_conditions = Array(finder_class.primary_key).zip(Array(record.send(:id))).map do |name, value|
|
14
|
+
table[name.to_sym].not_eq(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
condition = not_eq_conditions.shift
|
18
|
+
not_eq_conditions.each do |not_eq_condition|
|
19
|
+
condition = condition.or(not_eq_condition)
|
20
|
+
end
|
21
|
+
relation = relation.and(condition)
|
22
|
+
end
|
23
|
+
|
24
|
+
relation = scope_relation(record, table, relation)
|
25
|
+
relation = finder_class.unscoped.where(relation)
|
26
|
+
relation = relation.merge(options[:conditions]) if options[:conditions]
|
27
|
+
|
28
|
+
if relation.exists?
|
29
|
+
error_options = options.except(:case_sensitive, :scope, :conditions)
|
30
|
+
error_options[:value] = value
|
31
|
+
|
32
|
+
record.errors.add(attribute, :taken, error_options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
38
37
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module VERSION
|
3
|
-
MAJOR =
|
4
|
-
MINOR = 0
|
5
|
-
TINY =
|
6
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
7
|
-
end
|
8
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 8
|
4
|
+
MINOR = 0
|
5
|
+
TINY = 0
|
6
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
7
|
+
end
|
8
|
+
end
|
data/tasks/databases/oracle.rake
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
2
|
-
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
3
|
-
|
4
|
-
namespace :oracle do
|
5
|
-
desc 'Build the Oracle test database'
|
6
|
-
task :build_database => :load_connection do
|
7
|
-
options_str = connection_string
|
8
|
-
|
9
|
-
schema = File.join(PROJECT_ROOT, 'test', 'fixtures', 'db_definitions', 'oracle.sql')
|
10
|
-
sh %( sqlplus #{options_str} < #{schema} )
|
11
|
-
end
|
12
|
-
|
13
|
-
desc 'Drop the Oracle test database'
|
14
|
-
task :drop_database => :load_connection do
|
15
|
-
options_str = connection_string
|
16
|
-
sh %( sqlplus #{options_str} < #{File.join(SCHEMA_PATH, 'oracle.drop.sql')} )
|
17
|
-
end
|
18
|
-
|
19
|
-
desc 'Rebuild the Oracle test database'
|
20
|
-
task :rebuild_database => [:drop_database, :build_database]
|
21
|
-
|
22
|
-
task :load_connection do
|
23
|
-
require File.join(PROJECT_ROOT, "test", "connections", "native_oracle", "connection")
|
24
|
-
end
|
25
|
-
end
|
1
|
+
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
2
|
+
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
3
|
+
|
4
|
+
namespace :oracle do
|
5
|
+
desc 'Build the Oracle test database'
|
6
|
+
task :build_database => :load_connection do
|
7
|
+
options_str = connection_string
|
8
|
+
|
9
|
+
schema = File.join(PROJECT_ROOT, 'test', 'fixtures', 'db_definitions', 'oracle.sql')
|
10
|
+
sh %( sqlplus #{options_str} < #{schema} )
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Drop the Oracle test database'
|
14
|
+
task :drop_database => :load_connection do
|
15
|
+
options_str = connection_string
|
16
|
+
sh %( sqlplus #{options_str} < #{File.join(SCHEMA_PATH, 'oracle.drop.sql')} )
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Rebuild the Oracle test database'
|
20
|
+
task :rebuild_database => [:drop_database, :build_database]
|
21
|
+
|
22
|
+
task :load_connection do
|
23
|
+
require File.join(PROJECT_ROOT, "test", "connections", "native_oracle", "connection")
|
24
|
+
end
|
25
|
+
end
|
@@ -1,40 +1,27 @@
|
|
1
|
-
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
2
|
-
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
task :
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
'sqlserver.drop.sql').gsub(File::SEPARATOR,
|
29
|
-
File::ALT_SEPARATOR ||
|
30
|
-
File::SEPARATOR)
|
31
|
-
sh %( #{sql_cmd} #{options_str} -i #{schema} )
|
32
|
-
end
|
33
|
-
|
34
|
-
desc 'Rebuild the SQL Server test database'
|
35
|
-
task :rebuild_database => [:drop_database, :build_database]
|
36
|
-
|
37
|
-
task :load_connection do
|
38
|
-
require File.join(PROJECT_ROOT, "test", "connections", "native_sqlserver", "connection")
|
39
|
-
end
|
40
|
-
end
|
1
|
+
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
2
|
+
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
3
|
+
|
4
|
+
namespace :sqlserver do
|
5
|
+
desc 'Build the SQL Server test database'
|
6
|
+
task :build_database => :load_connection do
|
7
|
+
options_str = connection_string
|
8
|
+
|
9
|
+
schema = File.join(PROJECT_ROOT, 'test', 'fixtures', 'db_definitions', 'sqlserver.sql')
|
10
|
+
sh %( sqsh #{options_str} -i #{schema} )
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Drop the SQL Server test database'
|
14
|
+
task :drop_database => :load_connection do
|
15
|
+
options_str = connection_string
|
16
|
+
|
17
|
+
schema = File.join(PROJECT_ROOT, 'test', 'fixtures', 'db_definitions', 'sqlserver.drop.sql')
|
18
|
+
sh %( sqsh #{options_str} -i #{schema} )
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Rebuild the SQL Server test database'
|
22
|
+
task :rebuild_database => [:drop_database, :build_database]
|
23
|
+
|
24
|
+
task :load_connection do
|
25
|
+
require File.join(PROJECT_ROOT, "test", "connections", "native_sqlserver", "connection")
|
26
|
+
end
|
27
|
+
end
|
data/test/abstract_unit.rb
CHANGED
@@ -1,113 +1,113 @@
|
|
1
|
-
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
-
|
3
|
-
# To make debugging easier, test within this source tree versus an installed gem
|
4
|
-
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
5
|
-
require 'composite_primary_keys'
|
6
|
-
require 'minitest/autorun'
|
7
|
-
require 'active_support/test_case'
|
8
|
-
|
9
|
-
# Now load the connection spec
|
10
|
-
require File.join(PROJECT_ROOT, "test", "connections", "connection_spec")
|
11
|
-
|
12
|
-
spec_name = ENV['ADAPTER'] || 'postgresql'
|
13
|
-
spec = CompositePrimaryKeys::ConnectionSpec[spec_name]
|
14
|
-
|
15
|
-
# And now connect to the database
|
16
|
-
adapter = spec['adapter']
|
17
|
-
require File.join(PROJECT_ROOT, "test", "connections", "native_#{spec_name}", "connection")
|
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
|
-
|
25
|
-
I18n.config.enforce_available_locales = true
|
26
|
-
|
27
|
-
class ActiveSupport::TestCase
|
28
|
-
include ActiveRecord::TestFixtures
|
29
|
-
|
30
|
-
self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
31
|
-
self.use_instantiated_fixtures = false
|
32
|
-
self.use_transactional_fixtures = true
|
33
|
-
|
34
|
-
def assert_date_from_db(expected, actual, message = nil)
|
35
|
-
# SQL Server doesn't have a separate column type just for dates,
|
36
|
-
# so the time is in the string and incorrectly formatted
|
37
|
-
if current_adapter?(:SQLServerAdapter)
|
38
|
-
assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
|
39
|
-
elsif current_adapter?(:SybaseAdapter)
|
40
|
-
assert_equal expected.to_s, actual.to_date.to_s, message
|
41
|
-
else
|
42
|
-
assert_equal expected.to_s, actual.to_s, message
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def assert_queries(num = 1)
|
47
|
-
ActiveRecord::Base.connection.class.class_eval do
|
48
|
-
self.query_count = 0
|
49
|
-
alias_method :execute, :execute_with_query_counting
|
50
|
-
end
|
51
|
-
yield
|
52
|
-
ensure
|
53
|
-
ActiveRecord::Base.connection.class.class_eval do
|
54
|
-
alias_method :execute, :execute_without_query_counting
|
55
|
-
end
|
56
|
-
assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
|
57
|
-
end
|
58
|
-
|
59
|
-
def assert_no_queries(&block)
|
60
|
-
assert_queries(0, &block)
|
61
|
-
end
|
62
|
-
|
63
|
-
cattr_accessor :classes
|
64
|
-
|
65
|
-
protected
|
66
|
-
|
67
|
-
def testing_with(&block)
|
68
|
-
classes.keys.each do |key_test|
|
69
|
-
@key_test = key_test
|
70
|
-
@klass_info = classes[@key_test]
|
71
|
-
@klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
|
72
|
-
order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
|
73
|
-
@first = @klass.order(order).first
|
74
|
-
yield
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def first_id
|
79
|
-
ids = (1..@primary_keys.length).map {|num| 1}
|
80
|
-
composite? ? ids.to_composite_ids : ids.first
|
81
|
-
end
|
82
|
-
|
83
|
-
def composite?
|
84
|
-
@key_test != :single
|
85
|
-
end
|
86
|
-
|
87
|
-
# Oracle metadata is in all caps.
|
88
|
-
def with_quoted_identifiers(s)
|
89
|
-
s.gsub(/"(\w+)"/) { |m|
|
90
|
-
if ActiveRecord::Base.configurations[:test]['adapter'] =~ /oracle/i
|
91
|
-
m.upcase
|
92
|
-
else
|
93
|
-
m
|
94
|
-
end
|
95
|
-
}
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def current_adapter?(type)
|
100
|
-
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
101
|
-
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
|
102
|
-
end
|
103
|
-
|
104
|
-
ActiveRecord::Base.connection.class.class_eval do
|
105
|
-
cattr_accessor :query_count
|
106
|
-
alias_method :execute_without_query_counting, :execute
|
107
|
-
def execute_with_query_counting(sql, name = nil)
|
108
|
-
self.query_count += 1
|
109
|
-
execute_without_query_counting(sql, name)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
ActiveRecord::Base.logger = Logger.new(ENV['CPK_LOGFILE'] || STDOUT)
|
1
|
+
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
|
3
|
+
# To make debugging easier, test within this source tree versus an installed gem
|
4
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
5
|
+
require 'composite_primary_keys'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require 'active_support/test_case'
|
8
|
+
|
9
|
+
# Now load the connection spec
|
10
|
+
require File.join(PROJECT_ROOT, "test", "connections", "connection_spec")
|
11
|
+
|
12
|
+
spec_name = ENV['ADAPTER'] || 'postgresql'
|
13
|
+
spec = CompositePrimaryKeys::ConnectionSpec[spec_name]
|
14
|
+
|
15
|
+
# And now connect to the database
|
16
|
+
adapter = spec['adapter']
|
17
|
+
require File.join(PROJECT_ROOT, "test", "connections", "native_#{spec_name}", "connection")
|
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
|
+
|
25
|
+
I18n.config.enforce_available_locales = true
|
26
|
+
|
27
|
+
class ActiveSupport::TestCase
|
28
|
+
include ActiveRecord::TestFixtures
|
29
|
+
|
30
|
+
self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
31
|
+
self.use_instantiated_fixtures = false
|
32
|
+
self.use_transactional_fixtures = true
|
33
|
+
|
34
|
+
def assert_date_from_db(expected, actual, message = nil)
|
35
|
+
# SQL Server doesn't have a separate column type just for dates,
|
36
|
+
# so the time is in the string and incorrectly formatted
|
37
|
+
if current_adapter?(:SQLServerAdapter)
|
38
|
+
assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
|
39
|
+
elsif current_adapter?(:SybaseAdapter)
|
40
|
+
assert_equal expected.to_s, actual.to_date.to_s, message
|
41
|
+
else
|
42
|
+
assert_equal expected.to_s, actual.to_s, message
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def assert_queries(num = 1)
|
47
|
+
ActiveRecord::Base.connection.class.class_eval do
|
48
|
+
self.query_count = 0
|
49
|
+
alias_method :execute, :execute_with_query_counting
|
50
|
+
end
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
ActiveRecord::Base.connection.class.class_eval do
|
54
|
+
alias_method :execute, :execute_without_query_counting
|
55
|
+
end
|
56
|
+
assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
|
57
|
+
end
|
58
|
+
|
59
|
+
def assert_no_queries(&block)
|
60
|
+
assert_queries(0, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
cattr_accessor :classes
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def testing_with(&block)
|
68
|
+
classes.keys.each do |key_test|
|
69
|
+
@key_test = key_test
|
70
|
+
@klass_info = classes[@key_test]
|
71
|
+
@klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
|
72
|
+
order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
|
73
|
+
@first = @klass.order(order).first
|
74
|
+
yield
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def first_id
|
79
|
+
ids = (1..@primary_keys.length).map {|num| 1}
|
80
|
+
composite? ? ids.to_composite_ids : ids.first
|
81
|
+
end
|
82
|
+
|
83
|
+
def composite?
|
84
|
+
@key_test != :single
|
85
|
+
end
|
86
|
+
|
87
|
+
# Oracle metadata is in all caps.
|
88
|
+
def with_quoted_identifiers(s)
|
89
|
+
s.gsub(/"(\w+)"/) { |m|
|
90
|
+
if ActiveRecord::Base.configurations[:test]['adapter'] =~ /oracle/i
|
91
|
+
m.upcase
|
92
|
+
else
|
93
|
+
m
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def current_adapter?(type)
|
100
|
+
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
101
|
+
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
|
102
|
+
end
|
103
|
+
|
104
|
+
ActiveRecord::Base.connection.class.class_eval do
|
105
|
+
cattr_accessor :query_count
|
106
|
+
alias_method :execute_without_query_counting, :execute
|
107
|
+
def execute_with_query_counting(sql, name = nil)
|
108
|
+
self.query_count += 1
|
109
|
+
execute_without_query_counting(sql, name)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
ActiveRecord::Base.logger = Logger.new(ENV['CPK_LOGFILE'] || STDOUT)
|