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,30 +1,30 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
ID_SEP = ','
|
3
|
-
ID_SET_SEP = ';'
|
4
|
-
|
5
|
-
module ArrayExtension
|
6
|
-
def to_composite_keys
|
7
|
-
CompositeKeys.new(self)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class CompositeKeys < Array
|
12
|
-
def self.parse(value)
|
13
|
-
case value
|
14
|
-
when Array
|
15
|
-
value.to_composite_keys
|
16
|
-
when String
|
17
|
-
self.new(value.split(ID_SEP))
|
18
|
-
else
|
19
|
-
raise(ArgumentError, "Unsupported type: #{value}")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
# Doing this makes it easier to parse Base#[](attr_name)
|
25
|
-
join(ID_SEP)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
ID_SEP = ','
|
3
|
+
ID_SET_SEP = ';'
|
4
|
+
|
5
|
+
module ArrayExtension
|
6
|
+
def to_composite_keys
|
7
|
+
CompositeKeys.new(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class CompositeKeys < Array
|
12
|
+
def self.parse(value)
|
13
|
+
case value
|
14
|
+
when Array
|
15
|
+
value.to_composite_keys
|
16
|
+
when String
|
17
|
+
self.new(value.split(ID_SEP))
|
18
|
+
else
|
19
|
+
raise(ArgumentError, "Unsupported type: #{value}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
# Doing this makes it easier to parse Base#[](attr_name)
|
25
|
+
join(ID_SEP)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|
@@ -1,51 +1,51 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module Predicates
|
3
|
-
def cpk_and_predicate(predicates)
|
4
|
-
if predicates.length == 1
|
5
|
-
predicates.first
|
6
|
-
else
|
7
|
-
Arel::Nodes::And.new(predicates)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def cpk_or_predicate(predicates)
|
12
|
-
or_predicate = predicates.map do |predicate|
|
13
|
-
::Arel::Nodes::Grouping.new(predicate)
|
14
|
-
end.inject do |memo, node|
|
15
|
-
::Arel::Nodes::Or.new(memo, node)
|
16
|
-
end
|
17
|
-
::Arel::Nodes::Grouping.new(or_predicate)
|
18
|
-
end
|
19
|
-
|
20
|
-
def cpk_id_predicate(table, keys, values)
|
21
|
-
eq_predicates = keys.zip(values).map do |key, value|
|
22
|
-
table[key].eq(value)
|
23
|
-
end
|
24
|
-
cpk_and_predicate(eq_predicates)
|
25
|
-
end
|
26
|
-
|
27
|
-
def cpk_join_predicate(table1, key1, table2, key2)
|
28
|
-
key1_fields = Array(key1).map {|key| table1[key]}
|
29
|
-
key2_fields = Array(key2).map {|key| table2[key]}
|
30
|
-
|
31
|
-
eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
|
32
|
-
key_field1.eq(key_field2)
|
33
|
-
end
|
34
|
-
cpk_and_predicate(eq_predicates)
|
35
|
-
end
|
36
|
-
|
37
|
-
def cpk_in_predicate(table, primary_keys, ids)
|
38
|
-
and_predicates = ids.map do |id|
|
39
|
-
cpk_id_predicate(table, primary_keys, id)
|
40
|
-
end
|
41
|
-
cpk_or_predicate(and_predicates)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
|
47
|
-
ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
48
|
-
ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
|
49
|
-
ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
50
|
-
ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module Predicates
|
3
|
+
def cpk_and_predicate(predicates)
|
4
|
+
if predicates.length == 1
|
5
|
+
predicates.first
|
6
|
+
else
|
7
|
+
Arel::Nodes::And.new(predicates)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def cpk_or_predicate(predicates)
|
12
|
+
or_predicate = predicates.map do |predicate|
|
13
|
+
::Arel::Nodes::Grouping.new(predicate)
|
14
|
+
end.inject do |memo, node|
|
15
|
+
::Arel::Nodes::Or.new(memo, node)
|
16
|
+
end
|
17
|
+
::Arel::Nodes::Grouping.new(or_predicate)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cpk_id_predicate(table, keys, values)
|
21
|
+
eq_predicates = keys.zip(values).map do |key, value|
|
22
|
+
table[key].eq(value)
|
23
|
+
end
|
24
|
+
cpk_and_predicate(eq_predicates)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cpk_join_predicate(table1, key1, table2, key2)
|
28
|
+
key1_fields = Array(key1).map {|key| table1[key]}
|
29
|
+
key2_fields = Array(key2).map {|key| table2[key]}
|
30
|
+
|
31
|
+
eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
|
32
|
+
key_field1.eq(key_field2)
|
33
|
+
end
|
34
|
+
cpk_and_predicate(eq_predicates)
|
35
|
+
end
|
36
|
+
|
37
|
+
def cpk_in_predicate(table, primary_keys, ids)
|
38
|
+
and_predicates = ids.map do |id|
|
39
|
+
cpk_id_predicate(table, primary_keys, id)
|
40
|
+
end
|
41
|
+
cpk_or_predicate(and_predicates)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
|
47
|
+
ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
48
|
+
ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
|
49
|
+
ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
50
|
+
ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
|
51
51
|
ActiveRecord::PredicateBuilder.send(:extend, CompositePrimaryKeys::Predicates)
|
@@ -1,48 +1,48 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module CompositeRelation
|
3
|
-
include CompositePrimaryKeys::ActiveRecord::Batches
|
4
|
-
include CompositePrimaryKeys::ActiveRecord::Calculations
|
5
|
-
include CompositePrimaryKeys::ActiveRecord::FinderMethods
|
6
|
-
include CompositePrimaryKeys::ActiveRecord::QueryMethods
|
7
|
-
|
8
|
-
def delete(id_or_array)
|
9
|
-
# CPK
|
10
|
-
if self.composite?
|
11
|
-
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
12
|
-
[id_or_array]
|
13
|
-
else
|
14
|
-
Array(id_or_array)
|
15
|
-
end
|
16
|
-
|
17
|
-
id_or_array.each do |id|
|
18
|
-
# Is the passed in id actually a record?
|
19
|
-
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
20
|
-
where(cpk_id_predicate(table, self.primary_key, id)).delete_all
|
21
|
-
end
|
22
|
-
else
|
23
|
-
where(primary_key => id_or_array).delete_all
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def destroy(id_or_array)
|
28
|
-
# Without CPK:
|
29
|
-
#if id.is_a?(Array)
|
30
|
-
# id.map { |one_id| destroy(one_id) }
|
31
|
-
#else
|
32
|
-
# find(id).destroy
|
33
|
-
#end
|
34
|
-
|
35
|
-
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
36
|
-
[id_or_array]
|
37
|
-
else
|
38
|
-
Array(id_or_array)
|
39
|
-
end
|
40
|
-
|
41
|
-
id_or_array.each do |id|
|
42
|
-
where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
|
43
|
-
record.destroy
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module CompositeRelation
|
3
|
+
include CompositePrimaryKeys::ActiveRecord::Batches
|
4
|
+
include CompositePrimaryKeys::ActiveRecord::Calculations
|
5
|
+
include CompositePrimaryKeys::ActiveRecord::FinderMethods
|
6
|
+
include CompositePrimaryKeys::ActiveRecord::QueryMethods
|
7
|
+
|
8
|
+
def delete(id_or_array)
|
9
|
+
# CPK
|
10
|
+
if self.composite?
|
11
|
+
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
12
|
+
[id_or_array]
|
13
|
+
else
|
14
|
+
Array(id_or_array)
|
15
|
+
end
|
16
|
+
|
17
|
+
id_or_array.each do |id|
|
18
|
+
# Is the passed in id actually a record?
|
19
|
+
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
20
|
+
where(cpk_id_predicate(table, self.primary_key, id)).delete_all
|
21
|
+
end
|
22
|
+
else
|
23
|
+
where(primary_key => id_or_array).delete_all
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(id_or_array)
|
28
|
+
# Without CPK:
|
29
|
+
#if id.is_a?(Array)
|
30
|
+
# id.map { |one_id| destroy(one_id) }
|
31
|
+
#else
|
32
|
+
# find(id).destroy
|
33
|
+
#end
|
34
|
+
|
35
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
36
|
+
[id_or_array]
|
37
|
+
else
|
38
|
+
Array(id_or_array)
|
39
|
+
end
|
40
|
+
|
41
|
+
id_or_array.each do |id|
|
42
|
+
where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
|
43
|
+
record.destroy
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb
CHANGED
@@ -4,9 +4,6 @@ module ActiveRecord
|
|
4
4
|
if (adapter.to_s =~ /postgresql/) or (adapter.to_s =~ /postgis/)
|
5
5
|
require "composite_primary_keys/connection_adapters/postgresql_adapter.rb"
|
6
6
|
end
|
7
|
-
if (adapter.to_s =~ /sqlserver/)
|
8
|
-
require "composite_primary_keys/connection_adapters/sqlserver_adapter.rb"
|
9
|
-
end
|
10
7
|
end
|
11
8
|
|
12
9
|
def self.establish_connection(spec = ENV["DATABASE_URL"])
|
@@ -64,7 +61,8 @@ module ActiveRecord
|
|
64
61
|
connection_handler.clear_active_connections!
|
65
62
|
end
|
66
63
|
|
67
|
-
delegate :clear_reloadable_connections!,
|
64
|
+
delegate :clear_reloadable_connections!,
|
65
|
+
:clear_all_connections!,:verify_active_connections!, :to => :connection_handler
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|
@@ -1,60 +1,46 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionAdapters
|
3
|
-
class PostgreSQLAdapter
|
4
|
-
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
5
|
-
unless pk
|
6
|
-
# Extract the table from the insert sql. Yuck.
|
7
|
-
table_ref = extract_table_ref_from_insert_sql(sql)
|
8
|
-
pk = primary_key(table_ref) if table_ref
|
9
|
-
end
|
10
|
-
|
11
|
-
if pk
|
12
|
-
# CPK
|
13
|
-
# select_value("#{sql} RETURNING #{quote_column_name(pk)}")
|
14
|
-
select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
15
|
-
else
|
16
|
-
super
|
17
|
-
end
|
18
|
-
end
|
19
|
-
alias :create :insert
|
20
|
-
|
21
|
-
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
22
|
-
unless pk
|
23
|
-
# Extract the table from the insert sql. Yuck.
|
24
|
-
table_ref = extract_table_ref_from_insert_sql(sql)
|
25
|
-
pk = primary_key(table_ref) if table_ref
|
26
|
-
end
|
27
|
-
|
28
|
-
# CPK
|
29
|
-
# sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
|
30
|
-
sql = "#{sql} RETURNING #{quote_column_names(pk)}" if pk
|
31
|
-
|
32
|
-
[sql, binds]
|
33
|
-
end
|
34
|
-
|
35
|
-
# Returns a single value if query returns a single element
|
36
|
-
# otherwise returns an array coresponding to the composite keys
|
37
|
-
#
|
38
|
-
def last_inserted_id(result)
|
39
|
-
row = result && result.rows.first
|
40
|
-
if Array === row
|
41
|
-
row.size == 1 ? row[0] : row
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# CPK
|
48
|
-
# PGconn.quote_ident(name.to_s)
|
49
|
-
if name.is_a?(Array)
|
50
|
-
name.map do |column|
|
51
|
-
PGconn.quote_ident(column.to_s)
|
52
|
-
end.join(', ')
|
53
|
-
else
|
54
|
-
PGconn.quote_ident(name.to_s)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class PostgreSQLAdapter
|
4
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
5
|
+
unless pk
|
6
|
+
# Extract the table from the insert sql. Yuck.
|
7
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
8
|
+
pk = primary_key(table_ref) if table_ref
|
9
|
+
end
|
10
|
+
|
11
|
+
if pk
|
12
|
+
# CPK
|
13
|
+
# select_value("#{sql} RETURNING #{quote_column_name(pk)}")
|
14
|
+
select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias :create :insert
|
20
|
+
|
21
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
22
|
+
unless pk
|
23
|
+
# Extract the table from the insert sql. Yuck.
|
24
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
25
|
+
pk = primary_key(table_ref) if table_ref
|
26
|
+
end
|
27
|
+
|
28
|
+
# CPK
|
29
|
+
# sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
|
30
|
+
sql = "#{sql} RETURNING #{quote_column_names(pk)}" if pk
|
31
|
+
|
32
|
+
[sql, binds]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a single value if query returns a single element
|
36
|
+
# otherwise returns an array coresponding to the composite keys
|
37
|
+
#
|
38
|
+
def last_inserted_id(result)
|
39
|
+
row = result && result.rows.first
|
40
|
+
if Array === row
|
41
|
+
row.size == 1 ? row[0] : row
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,47 +1,69 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Core
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@
|
13
|
-
|
14
|
-
@
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Core
|
3
|
+
def initialize_dup(other) # :nodoc:
|
4
|
+
@attributes = @attributes.dup
|
5
|
+
# CPK
|
6
|
+
# @attributes.reset(self.class.primary_key)
|
7
|
+
Array(self.class.primary_key).each {|key| @attributes.reset(key)}
|
8
|
+
|
9
|
+
run_callbacks(:initialize) unless _initialize_callbacks.empty?
|
10
|
+
|
11
|
+
@aggregation_cache = {}
|
12
|
+
@association_cache = {}
|
13
|
+
|
14
|
+
@new_record = true
|
15
|
+
@destroyed = false
|
16
|
+
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
module CompositePrimaryKeys
|
26
|
+
module ActiveRecordCoreConcernIncludedExtension
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
included do
|
30
|
+
def self.find(*ids)
|
31
|
+
if composite?
|
32
|
+
super(cpk_parse_ids(ids))
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def self.cpk_parse_ids(ids)
|
40
|
+
result = []
|
41
|
+
ids.each do |id|
|
42
|
+
if id.is_a?(String)
|
43
|
+
if id.index(",")
|
44
|
+
result << [id.split(",")]
|
45
|
+
else
|
46
|
+
result << [id]
|
47
|
+
end
|
48
|
+
elsif id.is_a?(Array) && id.count > 1 && id.first.to_s.index(",")
|
49
|
+
result << id.map{|subid| subid.split(",")}
|
50
|
+
else
|
51
|
+
result << [id]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
copy_to_find_depth, depth = result.dup, -1
|
56
|
+
|
57
|
+
until copy_to_find_depth == result.flatten
|
58
|
+
depth += 1
|
59
|
+
copy_to_find_depth = copy_to_find_depth.flatten(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
result = result.flatten(depth)
|
63
|
+
return result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
ActiveRecord::Base.send(:include, CompositePrimaryKeys::ActiveRecordCoreConcernIncludedExtension)
|