composite_primary_keys 13.0.1 → 13.0.2
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 +891 -888
- data/README.rdoc +181 -181
- data/Rakefile +37 -37
- data/lib/composite_primary_keys/arel/sqlserver.rb +37 -37
- data/lib/composite_primary_keys/arel/to_sql.rb +18 -18
- data/lib/composite_primary_keys/associations/association.rb +23 -23
- data/lib/composite_primary_keys/associations/collection_association.rb +31 -31
- data/lib/composite_primary_keys/associations/foreign_association.rb +15 -15
- data/lib/composite_primary_keys/associations/has_many_association.rb +35 -35
- data/lib/composite_primary_keys/associations/{join_dependency.rb → join_association.rb} +1 -1
- data/lib/composite_primary_keys/associations/through_association.rb +25 -25
- data/lib/composite_primary_keys/autosave_association.rb +60 -60
- data/lib/composite_primary_keys/composite_arrays.rb +86 -86
- data/lib/composite_primary_keys/composite_relation.rb +29 -29
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
- data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +26 -26
- data/lib/composite_primary_keys/counter_cache.rb +15 -15
- data/lib/composite_primary_keys/fixtures.rb +21 -21
- data/lib/composite_primary_keys/persistence.rb +82 -82
- data/lib/composite_primary_keys/relation/calculations.rb +104 -104
- data/lib/composite_primary_keys/sanitization.rb +42 -42
- data/lib/composite_primary_keys/transactions.rb +34 -34
- data/lib/composite_primary_keys/validations/uniqueness.rb +31 -31
- data/lib/composite_primary_keys/version.rb +8 -8
- data/lib/composite_primary_keys.rb +118 -118
- data/scripts/console.rb +48 -48
- data/scripts/txt2html +76 -76
- data/scripts/txt2js +65 -65
- data/tasks/databases/mysql.rake +40 -40
- data/tasks/databases/oracle.rake +41 -41
- data/tasks/databases/postgresql.rake +38 -38
- data/tasks/databases/sqlite.rake +25 -25
- data/tasks/databases/sqlserver.rake +43 -43
- data/tasks/website.rake +18 -18
- data/test/README_tests.rdoc +56 -56
- data/test/abstract_unit.rb +114 -114
- data/test/connections/connection_spec.rb +27 -27
- data/test/connections/databases.example.yml +40 -40
- data/test/connections/databases.yml +40 -39
- data/test/fixtures/article.rb +10 -10
- data/test/fixtures/articles.yml +7 -7
- data/test/fixtures/capitol.rb +3 -3
- data/test/fixtures/capitols.yml +16 -16
- data/test/fixtures/comment.rb +5 -5
- data/test/fixtures/comments.yml +17 -17
- data/test/fixtures/department.rb +16 -16
- data/test/fixtures/dorm.rb +2 -2
- data/test/fixtures/dorms.yml +4 -4
- data/test/fixtures/employee.rb +5 -5
- data/test/fixtures/group.rb +2 -2
- data/test/fixtures/groups.yml +6 -6
- data/test/fixtures/membership.rb +8 -8
- data/test/fixtures/membership_status.rb +2 -2
- data/test/fixtures/membership_statuses.yml +16 -16
- data/test/fixtures/memberships.yml +10 -10
- data/test/fixtures/product.rb +9 -9
- data/test/fixtures/product_tariff.rb +5 -5
- data/test/fixtures/product_tariffs.yml +14 -14
- data/test/fixtures/products.yml +11 -11
- data/test/fixtures/reading.rb +4 -4
- data/test/fixtures/readings.yml +10 -10
- data/test/fixtures/reference_code.rb +7 -7
- data/test/fixtures/reference_codes.yml +28 -28
- data/test/fixtures/reference_type.rb +12 -12
- data/test/fixtures/reference_types.yml +9 -9
- data/test/fixtures/restaurant.rb +9 -9
- data/test/fixtures/restaurants.yml +14 -14
- data/test/fixtures/restaurants_suburb.rb +2 -2
- data/test/fixtures/room.rb +11 -11
- data/test/fixtures/room_assignment.rb +13 -13
- data/test/fixtures/room_assignments.yml +24 -24
- data/test/fixtures/room_attribute.rb +2 -2
- data/test/fixtures/room_attribute_assignment.rb +4 -4
- data/test/fixtures/room_attribute_assignments.yml +4 -4
- data/test/fixtures/room_attributes.yml +2 -2
- data/test/fixtures/rooms.yml +12 -12
- data/test/fixtures/street.rb +2 -2
- data/test/fixtures/student.rb +3 -3
- data/test/fixtures/students.yml +15 -15
- data/test/fixtures/suburb.rb +5 -5
- data/test/fixtures/tariff.rb +5 -5
- data/test/fixtures/tariffs.yml +14 -14
- data/test/fixtures/topic_sources.yml +3 -3
- data/test/fixtures/topics.yml +8 -8
- data/test/fixtures/users.yml +10 -10
- data/test/plugins/pagination.rb +405 -405
- data/test/plugins/pagination_helper.rb +135 -135
- data/test/test_associations.rb +372 -372
- data/test/test_attribute_methods.rb +63 -63
- data/test/test_callbacks.rb +99 -99
- data/test/test_composite_arrays.rb +38 -38
- data/test/test_counter_cache.rb +30 -30
- data/test/test_dumpable.rb +15 -15
- data/test/test_dup.rb +37 -37
- data/test/test_equal.rb +26 -26
- data/test/test_habtm.rb +141 -141
- data/test/test_miscellaneous.rb +32 -32
- data/test/test_optimistic.rb +18 -18
- data/test/test_pagination.rb +35 -35
- data/test/test_polymorphic.rb +43 -43
- data/test/test_predicates.rb +59 -59
- data/test/test_preload.rb +102 -102
- data/test/test_santiago.rb +23 -23
- data/test/test_touch.rb +23 -23
- data/test/test_tutorial_example.rb +25 -25
- data/test/test_validations.rb +13 -13
- metadata +4 -4
@@ -1,82 +1,82 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Persistence
|
3
|
-
module ClassMethods
|
4
|
-
def delete(id_or_array)
|
5
|
-
# CPK
|
6
|
-
if self.composite?
|
7
|
-
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
8
|
-
[id_or_array]
|
9
|
-
else
|
10
|
-
Array(id_or_array)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Delete should return the number of deleted records
|
14
|
-
id_or_array.map do |id|
|
15
|
-
# Is the passed in id actually a record?
|
16
|
-
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
17
|
-
delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
|
18
|
-
end.sum
|
19
|
-
else
|
20
|
-
delete_by(primary_key => id_or_array)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def _update_record(values, constraints) # :nodoc:
|
25
|
-
# CPK
|
26
|
-
if self.composite? && constraints[primary_key]
|
27
|
-
primary_key_values = constraints.delete(primary_key)
|
28
|
-
primary_key.each_with_index do |key, i|
|
29
|
-
constraints[key] = primary_key_values[i]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
34
|
-
|
35
|
-
um = arel_table.where(
|
36
|
-
constraints.reduce(&:and)
|
37
|
-
).compile_update(_substitute_values(values), primary_key)
|
38
|
-
|
39
|
-
connection.update(um, "#{self} Update")
|
40
|
-
end
|
41
|
-
|
42
|
-
def _delete_record(constraints) # :nodoc:
|
43
|
-
# CPK
|
44
|
-
if self.composite? && constraints[primary_key]
|
45
|
-
primary_key_values = constraints.delete(primary_key)
|
46
|
-
primary_key.each_with_index do |key, i|
|
47
|
-
constraints[key] = primary_key_values[i]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
52
|
-
|
53
|
-
dm = Arel::DeleteManager.new
|
54
|
-
dm.from(arel_table)
|
55
|
-
dm.wheres = constraints
|
56
|
-
|
57
|
-
connection.delete(dm, "#{self} Destroy")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def _create_record(attribute_names = self.attribute_names)
|
62
|
-
attribute_names = attributes_for_create(attribute_names)
|
63
|
-
|
64
|
-
new_id = self.class._insert_record(
|
65
|
-
attributes_with_values(attribute_names)
|
66
|
-
)
|
67
|
-
|
68
|
-
# CPK
|
69
|
-
if self.composite?
|
70
|
-
self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
|
71
|
-
else
|
72
|
-
self.id ||= new_id if self.class.primary_key
|
73
|
-
end
|
74
|
-
|
75
|
-
@new_record = false
|
76
|
-
|
77
|
-
yield(self) if block_given?
|
78
|
-
|
79
|
-
id
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Persistence
|
3
|
+
module ClassMethods
|
4
|
+
def delete(id_or_array)
|
5
|
+
# CPK
|
6
|
+
if self.composite?
|
7
|
+
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
8
|
+
[id_or_array]
|
9
|
+
else
|
10
|
+
Array(id_or_array)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Delete should return the number of deleted records
|
14
|
+
id_or_array.map do |id|
|
15
|
+
# Is the passed in id actually a record?
|
16
|
+
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
17
|
+
delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
|
18
|
+
end.sum
|
19
|
+
else
|
20
|
+
delete_by(primary_key => id_or_array)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def _update_record(values, constraints) # :nodoc:
|
25
|
+
# CPK
|
26
|
+
if self.composite? && constraints[primary_key]
|
27
|
+
primary_key_values = constraints.delete(primary_key)
|
28
|
+
primary_key.each_with_index do |key, i|
|
29
|
+
constraints[key] = primary_key_values[i]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
34
|
+
|
35
|
+
um = arel_table.where(
|
36
|
+
constraints.reduce(&:and)
|
37
|
+
).compile_update(_substitute_values(values), primary_key)
|
38
|
+
|
39
|
+
connection.update(um, "#{self} Update")
|
40
|
+
end
|
41
|
+
|
42
|
+
def _delete_record(constraints) # :nodoc:
|
43
|
+
# CPK
|
44
|
+
if self.composite? && constraints[primary_key]
|
45
|
+
primary_key_values = constraints.delete(primary_key)
|
46
|
+
primary_key.each_with_index do |key, i|
|
47
|
+
constraints[key] = primary_key_values[i]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
52
|
+
|
53
|
+
dm = Arel::DeleteManager.new
|
54
|
+
dm.from(arel_table)
|
55
|
+
dm.wheres = constraints
|
56
|
+
|
57
|
+
connection.delete(dm, "#{self} Destroy")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def _create_record(attribute_names = self.attribute_names)
|
62
|
+
attribute_names = attributes_for_create(attribute_names)
|
63
|
+
|
64
|
+
new_id = self.class._insert_record(
|
65
|
+
attributes_with_values(attribute_names)
|
66
|
+
)
|
67
|
+
|
68
|
+
# CPK
|
69
|
+
if self.composite?
|
70
|
+
self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
|
71
|
+
else
|
72
|
+
self.id ||= new_id if self.class.primary_key
|
73
|
+
end
|
74
|
+
|
75
|
+
@new_record = false
|
76
|
+
|
77
|
+
yield(self) if block_given?
|
78
|
+
|
79
|
+
id
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -1,104 +1,104 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module ActiveRecord
|
3
|
-
module Calculations
|
4
|
-
def aggregate_column(column_name)
|
5
|
-
# CPK
|
6
|
-
if column_name.kind_of?(Array)
|
7
|
-
# Note: Test don't seem to run this code?
|
8
|
-
column_name.map do |column|
|
9
|
-
@klass.arel_table[column]
|
10
|
-
end
|
11
|
-
elsif @klass.has_attribute?(column_name) || @klass.attribute_alias?(column_name)
|
12
|
-
@klass.arel_table[column_name]
|
13
|
-
else
|
14
|
-
Arel.sql(column_name == :all ? "*" : column_name.to_s)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
|
19
|
-
column_alias = column_name
|
20
|
-
|
21
|
-
# CPK
|
22
|
-
# if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
|
23
|
-
# # Shortcut when limit is zero.
|
24
|
-
# return 0 if limit_value == 0
|
25
|
-
#
|
26
|
-
# query_builder = build_count_subquery(spawn, column_name, distinct)
|
27
|
-
if operation == "count"
|
28
|
-
relation = unscope(:order)
|
29
|
-
query_builder = build_count_subquery(spawn, column_name, distinct)
|
30
|
-
else
|
31
|
-
# PostgreSQL doesn't like ORDER BY when there are no GROUP BY
|
32
|
-
relation = unscope(:order).distinct!(false)
|
33
|
-
|
34
|
-
column = aggregate_column(column_name)
|
35
|
-
select_value = operation_over_aggregate_column(column, operation, distinct)
|
36
|
-
select_value.distinct = true if operation == "sum" && distinct
|
37
|
-
|
38
|
-
relation.select_values = [select_value]
|
39
|
-
|
40
|
-
query_builder = relation.arel
|
41
|
-
end
|
42
|
-
|
43
|
-
result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
|
44
|
-
|
45
|
-
type_cast_calculated_value(result.cast_values.first, operation) do |value|
|
46
|
-
type = column.try(:type_caster) ||
|
47
|
-
# CPK
|
48
|
-
# lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
|
49
|
-
lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
|
50
|
-
type.deserialize(value)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def build_count_subquery(relation, column_name, distinct)
|
55
|
-
if column_name == :all
|
56
|
-
column_alias = Arel.star
|
57
|
-
# CPK
|
58
|
-
# relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
|
59
|
-
relation.select_values = [ Arel.sql(::ActiveRecord::FinderMethods::ONE_AS_ONE) ] unless distinct
|
60
|
-
elsif column_name.is_a?(Array)
|
61
|
-
column_alias = Arel.star
|
62
|
-
relation.select_values = column_name.map do |column|
|
63
|
-
Arel::Attribute.new(@klass.unscoped.table, column)
|
64
|
-
end
|
65
|
-
else
|
66
|
-
column_alias = Arel.sql("count_column")
|
67
|
-
relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
|
68
|
-
end
|
69
|
-
|
70
|
-
subquery_alias = Arel.sql("subquery_for_count")
|
71
|
-
select_value = operation_over_aggregate_column(column_alias, "count", false)
|
72
|
-
|
73
|
-
relation.build_subquery(subquery_alias, select_value)
|
74
|
-
end
|
75
|
-
|
76
|
-
def calculate(operation, column_name)
|
77
|
-
if has_include?(column_name)
|
78
|
-
relation = apply_join_dependency
|
79
|
-
|
80
|
-
if operation.to_s.downcase == "count"
|
81
|
-
unless distinct_value || distinct_select?(column_name || select_for_count)
|
82
|
-
relation.distinct!
|
83
|
-
# CPK
|
84
|
-
# relation.select_values = [ klass.primary_key || table[Arel.star] ]
|
85
|
-
if klass.primary_key.present? && klass.primary_key.is_a?(Array)
|
86
|
-
relation.select_values = klass.primary_key.map do |k|
|
87
|
-
"#{connection.quote_table_name(klass.table_name)}.#{connection.quote_column_name(k)}"
|
88
|
-
end
|
89
|
-
else
|
90
|
-
relation.select_values = [ klass.primary_key || table[Arel.star] ]
|
91
|
-
end
|
92
|
-
end
|
93
|
-
# PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
|
94
|
-
relation.order_values = [] if group_values.empty?
|
95
|
-
end
|
96
|
-
|
97
|
-
relation.calculate(operation, column_name)
|
98
|
-
else
|
99
|
-
perform_calculation(operation, column_name)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module ActiveRecord
|
3
|
+
module Calculations
|
4
|
+
def aggregate_column(column_name)
|
5
|
+
# CPK
|
6
|
+
if column_name.kind_of?(Array)
|
7
|
+
# Note: Test don't seem to run this code?
|
8
|
+
column_name.map do |column|
|
9
|
+
@klass.arel_table[column]
|
10
|
+
end
|
11
|
+
elsif @klass.has_attribute?(column_name) || @klass.attribute_alias?(column_name)
|
12
|
+
@klass.arel_table[column_name]
|
13
|
+
else
|
14
|
+
Arel.sql(column_name == :all ? "*" : column_name.to_s)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
|
19
|
+
column_alias = column_name
|
20
|
+
|
21
|
+
# CPK
|
22
|
+
# if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
|
23
|
+
# # Shortcut when limit is zero.
|
24
|
+
# return 0 if limit_value == 0
|
25
|
+
#
|
26
|
+
# query_builder = build_count_subquery(spawn, column_name, distinct)
|
27
|
+
if operation == "count"
|
28
|
+
relation = unscope(:order)
|
29
|
+
query_builder = build_count_subquery(spawn, column_name, distinct)
|
30
|
+
else
|
31
|
+
# PostgreSQL doesn't like ORDER BY when there are no GROUP BY
|
32
|
+
relation = unscope(:order).distinct!(false)
|
33
|
+
|
34
|
+
column = aggregate_column(column_name)
|
35
|
+
select_value = operation_over_aggregate_column(column, operation, distinct)
|
36
|
+
select_value.distinct = true if operation == "sum" && distinct
|
37
|
+
|
38
|
+
relation.select_values = [select_value]
|
39
|
+
|
40
|
+
query_builder = relation.arel
|
41
|
+
end
|
42
|
+
|
43
|
+
result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder) }
|
44
|
+
|
45
|
+
type_cast_calculated_value(result.cast_values.first, operation) do |value|
|
46
|
+
type = column.try(:type_caster) ||
|
47
|
+
# CPK
|
48
|
+
# lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
|
49
|
+
lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
|
50
|
+
type.deserialize(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_count_subquery(relation, column_name, distinct)
|
55
|
+
if column_name == :all
|
56
|
+
column_alias = Arel.star
|
57
|
+
# CPK
|
58
|
+
# relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
|
59
|
+
relation.select_values = [ Arel.sql(::ActiveRecord::FinderMethods::ONE_AS_ONE) ] unless distinct
|
60
|
+
elsif column_name.is_a?(Array)
|
61
|
+
column_alias = Arel.star
|
62
|
+
relation.select_values = column_name.map do |column|
|
63
|
+
Arel::Attribute.new(@klass.unscoped.table, column)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
column_alias = Arel.sql("count_column")
|
67
|
+
relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
|
68
|
+
end
|
69
|
+
|
70
|
+
subquery_alias = Arel.sql("subquery_for_count")
|
71
|
+
select_value = operation_over_aggregate_column(column_alias, "count", false)
|
72
|
+
|
73
|
+
relation.build_subquery(subquery_alias, select_value)
|
74
|
+
end
|
75
|
+
|
76
|
+
def calculate(operation, column_name)
|
77
|
+
if has_include?(column_name)
|
78
|
+
relation = apply_join_dependency
|
79
|
+
|
80
|
+
if operation.to_s.downcase == "count"
|
81
|
+
unless distinct_value || distinct_select?(column_name || select_for_count)
|
82
|
+
relation.distinct!
|
83
|
+
# CPK
|
84
|
+
# relation.select_values = [ klass.primary_key || table[Arel.star] ]
|
85
|
+
if klass.primary_key.present? && klass.primary_key.is_a?(Array)
|
86
|
+
relation.select_values = klass.primary_key.map do |k|
|
87
|
+
"#{connection.quote_table_name(klass.table_name)}.#{connection.quote_column_name(k)}"
|
88
|
+
end
|
89
|
+
else
|
90
|
+
relation.select_values = [ klass.primary_key || table[Arel.star] ]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
# PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
|
94
|
+
relation.order_values = [] if group_values.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
relation.calculate(operation, column_name)
|
98
|
+
else
|
99
|
+
perform_calculation(operation, column_name)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -1,43 +1,43 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Sanitization
|
3
|
-
module ClassMethods
|
4
|
-
# def expand_hash_conditions_for_aggregates(attrs)
|
5
|
-
# expanded_attrs = {}
|
6
|
-
# attrs.each do |attr, value|
|
7
|
-
# # CPK
|
8
|
-
# # if aggregation = reflect_on_aggregation(attr.to_sym)
|
9
|
-
# if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
|
10
|
-
# value = value.split('/') if value.is_a?(String)
|
11
|
-
# attr.each_with_index do |key,i|
|
12
|
-
# expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
|
13
|
-
# end
|
14
|
-
# elsif aggregation = reflect_on_aggregation(attr.to_sym)
|
15
|
-
# mapping = aggregation.mapping
|
16
|
-
# mapping.each do |field_attr, aggregate_attr|
|
17
|
-
# if mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
18
|
-
# expanded_attrs[field_attr] = value
|
19
|
-
# else
|
20
|
-
# expanded_attrs[field_attr] = value.send(aggregate_attr)
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
# else
|
24
|
-
# expanded_attrs[attr] = value
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
# expanded_attrs
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# def quoted_id
|
31
|
-
# # CPK
|
32
|
-
# # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
|
33
|
-
# if self.composite?
|
34
|
-
# [self.class.primary_keys, ids].transpose.map { |attr_name,id|
|
35
|
-
# self.class.quote_value(@attributes[attr_name].value_for_database)
|
36
|
-
# }
|
37
|
-
# else
|
38
|
-
# self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
end
|
42
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Sanitization
|
3
|
+
module ClassMethods
|
4
|
+
# def expand_hash_conditions_for_aggregates(attrs)
|
5
|
+
# expanded_attrs = {}
|
6
|
+
# attrs.each do |attr, value|
|
7
|
+
# # CPK
|
8
|
+
# # if aggregation = reflect_on_aggregation(attr.to_sym)
|
9
|
+
# if attr.is_a?(CompositePrimaryKeys::CompositeKeys)
|
10
|
+
# value = value.split('/') if value.is_a?(String)
|
11
|
+
# attr.each_with_index do |key,i|
|
12
|
+
# expanded_attrs[key] = value.respond_to?(:flatten) ? value.flatten[i] : value
|
13
|
+
# end
|
14
|
+
# elsif aggregation = reflect_on_aggregation(attr.to_sym)
|
15
|
+
# mapping = aggregation.mapping
|
16
|
+
# mapping.each do |field_attr, aggregate_attr|
|
17
|
+
# if mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
18
|
+
# expanded_attrs[field_attr] = value
|
19
|
+
# else
|
20
|
+
# expanded_attrs[field_attr] = value.send(aggregate_attr)
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# else
|
24
|
+
# expanded_attrs[attr] = value
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# expanded_attrs
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# def quoted_id
|
31
|
+
# # CPK
|
32
|
+
# # self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
|
33
|
+
# if self.composite?
|
34
|
+
# [self.class.primary_keys, ids].transpose.map { |attr_name,id|
|
35
|
+
# self.class.quote_value(@attributes[attr_name].value_for_database)
|
36
|
+
# }
|
37
|
+
# else
|
38
|
+
# self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
end
|
42
|
+
end
|
43
43
|
end
|
@@ -1,34 +1,34 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Transactions
|
3
|
-
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
4
|
-
def restore_transaction_record_state(force_restore_state = false)
|
5
|
-
if restore_state = @_start_transaction_state
|
6
|
-
if force_restore_state || restore_state[:level] <= 1
|
7
|
-
@new_record = restore_state[:new_record]
|
8
|
-
@destroyed = restore_state[:destroyed]
|
9
|
-
@attributes = restore_state[:attributes].map do |attr|
|
10
|
-
value = @attributes.fetch_value(attr.name)
|
11
|
-
attr = attr.with_value_from_user(value) if attr.value != value
|
12
|
-
attr
|
13
|
-
end
|
14
|
-
@mutations_from_database = nil
|
15
|
-
@mutations_before_last_save = nil
|
16
|
-
|
17
|
-
# CPK
|
18
|
-
if self.composite?
|
19
|
-
values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
|
20
|
-
restore_id = restore_state[:id]
|
21
|
-
if values != restore_id
|
22
|
-
@primary_key.each_with_index do |attribute, i|
|
23
|
-
@attributes.write_from_user(attribute, restore_id[i])
|
24
|
-
end
|
25
|
-
end
|
26
|
-
elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
|
27
|
-
@attributes.write_from_user(@primary_key, restore_state[:id])
|
28
|
-
end
|
29
|
-
freeze if restore_state[:frozen?]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Transactions
|
3
|
+
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
4
|
+
def restore_transaction_record_state(force_restore_state = false)
|
5
|
+
if restore_state = @_start_transaction_state
|
6
|
+
if force_restore_state || restore_state[:level] <= 1
|
7
|
+
@new_record = restore_state[:new_record]
|
8
|
+
@destroyed = restore_state[:destroyed]
|
9
|
+
@attributes = restore_state[:attributes].map do |attr|
|
10
|
+
value = @attributes.fetch_value(attr.name)
|
11
|
+
attr = attr.with_value_from_user(value) if attr.value != value
|
12
|
+
attr
|
13
|
+
end
|
14
|
+
@mutations_from_database = nil
|
15
|
+
@mutations_before_last_save = nil
|
16
|
+
|
17
|
+
# CPK
|
18
|
+
if self.composite?
|
19
|
+
values = @primary_key.map {|attribute| @attributes.fetch_value(attribute)}
|
20
|
+
restore_id = restore_state[:id]
|
21
|
+
if values != restore_id
|
22
|
+
@primary_key.each_with_index do |attribute, i|
|
23
|
+
@attributes.write_from_user(attribute, restore_id[i])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
elsif @attributes.fetch_value(@primary_key) != restore_state[:id]
|
27
|
+
@attributes.write_from_user(@primary_key, restore_state[:id])
|
28
|
+
end
|
29
|
+
freeze if restore_state[:frozen?]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,32 +1,32 @@
|
|
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
|
-
value = map_enum_attribute(finder_class, attribute, value)
|
7
|
-
|
8
|
-
relation = build_relation(finder_class, attribute, value)
|
9
|
-
if record.persisted?
|
10
|
-
# CPK
|
11
|
-
if finder_class.primary_key.is_a?(Array)
|
12
|
-
predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
|
13
|
-
relation = relation.where.not(predicate)
|
14
|
-
elsif finder_class.primary_key
|
15
|
-
relation = relation.where.not(finder_class.primary_key => record.id_in_database)
|
16
|
-
else
|
17
|
-
raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
|
18
|
-
end
|
19
|
-
end
|
20
|
-
relation = scope_relation(record, relation)
|
21
|
-
relation = relation.merge(options[:conditions]) if options[:conditions]
|
22
|
-
|
23
|
-
if relation.exists?
|
24
|
-
error_options = options.except(:case_sensitive, :scope, :conditions)
|
25
|
-
error_options[:value] = value
|
26
|
-
|
27
|
-
record.errors.add(attribute, :taken, **error_options)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
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
|
+
value = map_enum_attribute(finder_class, attribute, value)
|
7
|
+
|
8
|
+
relation = build_relation(finder_class, attribute, value)
|
9
|
+
if record.persisted?
|
10
|
+
# CPK
|
11
|
+
if finder_class.primary_key.is_a?(Array)
|
12
|
+
predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
|
13
|
+
relation = relation.where.not(predicate)
|
14
|
+
elsif finder_class.primary_key
|
15
|
+
relation = relation.where.not(finder_class.primary_key => record.id_in_database)
|
16
|
+
else
|
17
|
+
raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
relation = scope_relation(record, relation)
|
21
|
+
relation = relation.merge(options[:conditions]) if options[:conditions]
|
22
|
+
|
23
|
+
if relation.exists?
|
24
|
+
error_options = options.except(:case_sensitive, :scope, :conditions)
|
25
|
+
error_options[:value] = value
|
26
|
+
|
27
|
+
record.errors.add(attribute, :taken, **error_options)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
32
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module VERSION
|
3
|
-
MAJOR = 13
|
4
|
-
MINOR = 0
|
5
|
-
TINY =
|
6
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
7
|
-
end
|
8
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 13
|
4
|
+
MINOR = 0
|
5
|
+
TINY = 2
|
6
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
7
|
+
end
|
8
|
+
end
|