composite_primary_keys 8.1.6 → 9.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +5 -5
  2. data/History.rdoc +59 -7
  3. data/README.rdoc +62 -1
  4. data/Rakefile +4 -1
  5. data/lib/composite_primary_keys/arel/in.rb +6 -0
  6. data/lib/composite_primary_keys/arel/sqlserver.rb +36 -0
  7. data/lib/composite_primary_keys/arel/to_sql.rb +26 -0
  8. data/lib/composite_primary_keys/associations/association.rb +14 -12
  9. data/lib/composite_primary_keys/associations/association_scope.rb +22 -27
  10. data/lib/composite_primary_keys/associations/collection_association.rb +39 -8
  11. data/lib/composite_primary_keys/associations/has_many_association.rb +17 -40
  12. data/lib/composite_primary_keys/associations/has_many_through_association.rb +58 -58
  13. data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +13 -11
  14. data/lib/composite_primary_keys/associations/join_dependency.rb +73 -56
  15. data/lib/composite_primary_keys/associations/preloader/association.rb +75 -73
  16. data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -11
  17. data/lib/composite_primary_keys/attribute_methods/read.rb +18 -15
  18. data/lib/composite_primary_keys/attribute_methods/write.rb +21 -19
  19. data/lib/composite_primary_keys/attribute_methods.rb +6 -4
  20. data/lib/composite_primary_keys/autosave_association.rb +19 -54
  21. data/lib/composite_primary_keys/base.rb +18 -82
  22. data/lib/composite_primary_keys/composite_arrays.rb +9 -1
  23. data/lib/composite_primary_keys/composite_predicates.rb +1 -0
  24. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
  25. data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +5 -6
  26. data/lib/composite_primary_keys/connection_adapters/sqlite3_adapter.rb +23 -0
  27. data/lib/composite_primary_keys/core.rb +46 -45
  28. data/lib/composite_primary_keys/fixtures.rb +19 -17
  29. data/lib/composite_primary_keys/locking/optimistic.rb +53 -49
  30. data/lib/composite_primary_keys/nested_attributes.rb +60 -53
  31. data/lib/composite_primary_keys/persistence.rb +49 -41
  32. data/lib/composite_primary_keys/relation/batches.rb +35 -32
  33. data/lib/composite_primary_keys/relation/calculations.rb +3 -7
  34. data/lib/composite_primary_keys/relation/finder_methods.rb +122 -55
  35. data/lib/composite_primary_keys/relation/predicate_builder.rb +18 -29
  36. data/lib/composite_primary_keys/relation/query_methods.rb +25 -36
  37. data/lib/composite_primary_keys/relation/where_clause.rb +33 -0
  38. data/lib/composite_primary_keys/relation.rb +96 -43
  39. data/lib/composite_primary_keys/sanitization.rb +6 -15
  40. data/lib/composite_primary_keys/version.rb +3 -3
  41. data/lib/composite_primary_keys.rb +10 -19
  42. data/scripts/console.rb +48 -48
  43. data/scripts/txt2html +76 -76
  44. data/scripts/txt2js +65 -65
  45. data/tasks/databases/mysql.rake +17 -19
  46. data/tasks/databases/oracle.rake +29 -15
  47. data/tasks/databases/postgresql.rake +20 -29
  48. data/tasks/databases/sqlite.rake +25 -0
  49. data/tasks/databases/sqlserver.rake +32 -16
  50. data/tasks/website.rake +18 -18
  51. data/test/README_tests.rdoc +56 -56
  52. data/test/abstract_unit.rb +24 -18
  53. data/test/connections/connection_spec.rb +11 -2
  54. data/test/connections/databases.ci.yml +5 -4
  55. data/test/connections/databases.example.yml +19 -4
  56. data/test/connections/databases.yml +40 -30
  57. data/test/db_test.rb +52 -52
  58. data/test/fixtures/article.rb +1 -0
  59. data/test/fixtures/articles.yml +6 -6
  60. data/test/fixtures/capitol.rb +3 -3
  61. data/test/fixtures/capitols.yml +16 -16
  62. data/test/fixtures/comments.yml +15 -15
  63. data/test/fixtures/db_definitions/mysql.sql +16 -17
  64. data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
  65. data/test/fixtures/db_definitions/oracle.sql +26 -17
  66. data/test/fixtures/db_definitions/postgresql.sql +2 -3
  67. data/test/fixtures/db_definitions/sqlite.sql +0 -1
  68. data/test/fixtures/db_definitions/sqlserver.sql +20 -35
  69. data/test/fixtures/department.rb +5 -5
  70. data/test/fixtures/departments.yml +15 -15
  71. data/test/fixtures/dorms.yml +4 -4
  72. data/test/fixtures/employee.rb +5 -7
  73. data/test/fixtures/employees.yml +1 -5
  74. data/test/fixtures/group.rb +2 -2
  75. data/test/fixtures/groups.yml +6 -6
  76. data/test/fixtures/hack.rb +4 -4
  77. data/test/fixtures/hacks.yml +2 -2
  78. data/test/fixtures/membership_status.rb +2 -2
  79. data/test/fixtures/product.rb +9 -9
  80. data/test/fixtures/product_tariff.rb +5 -5
  81. data/test/fixtures/products.yml +11 -11
  82. data/test/fixtures/reading.rb +4 -4
  83. data/test/fixtures/readings.yml +10 -10
  84. data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
  85. data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
  86. data/test/fixtures/reference_codes.yml +28 -28
  87. data/test/fixtures/reference_type.rb +1 -1
  88. data/test/fixtures/reference_types.yml +9 -9
  89. data/test/fixtures/restaurant.rb +9 -9
  90. data/test/fixtures/restaurants.yml +14 -14
  91. data/test/fixtures/restaurants_suburbs.yml +10 -10
  92. data/test/fixtures/room.rb +11 -11
  93. data/test/fixtures/room_assignment.rb +13 -13
  94. data/test/fixtures/room_assignments.yml +24 -24
  95. data/test/fixtures/room_attribute.rb +2 -2
  96. data/test/fixtures/room_attribute_assignment.rb +4 -4
  97. data/test/fixtures/room_attribute_assignments.yml +4 -4
  98. data/test/fixtures/room_attributes.yml +2 -2
  99. data/test/fixtures/rooms.yml +12 -12
  100. data/test/fixtures/seat.rb +5 -5
  101. data/test/fixtures/seats.yml +8 -8
  102. data/test/fixtures/street.rb +2 -2
  103. data/test/fixtures/streets.yml +16 -16
  104. data/test/fixtures/student.rb +3 -3
  105. data/test/fixtures/students.yml +15 -15
  106. data/test/fixtures/suburbs.yml +14 -14
  107. data/test/fixtures/tariff.rb +1 -1
  108. data/test/fixtures/tariffs.yml +14 -14
  109. data/test/fixtures/user.rb +0 -1
  110. data/test/plugins/pagination.rb +405 -405
  111. data/test/plugins/pagination_helper.rb +135 -135
  112. data/test/setup.rb +50 -50
  113. data/test/test_aliases.rb +18 -18
  114. data/test/test_associations.rb +18 -17
  115. data/test/test_composite_arrays.rb +24 -24
  116. data/test/test_counter_cache.rb +30 -30
  117. data/test/test_create.rb +14 -6
  118. data/test/test_delete.rb +36 -34
  119. data/test/test_dup.rb +37 -37
  120. data/test/test_exists.rb +39 -39
  121. data/test/test_find.rb +16 -4
  122. data/test/test_habtm.rb +27 -3
  123. data/test/test_miscellaneous.rb +32 -32
  124. data/test/test_nested_attributes.rb +6 -6
  125. data/test/test_pagination.rb +35 -35
  126. data/test/test_polymorphic.rb +0 -7
  127. data/test/test_predicates.rb +20 -20
  128. data/test/test_preload.rb +94 -0
  129. data/test/test_suite.rb +1 -1
  130. data/test/test_update.rb +10 -7
  131. data/test/test_validations.rb +13 -13
  132. metadata +30 -39
  133. data/README_DB2.rdoc +0 -33
  134. data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -36
  135. data/lib/composite_primary_keys/associations/singular_association.rb +0 -18
  136. data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -29
  137. data/lib/composite_primary_keys/attribute_set/builder.rb +0 -20
  138. data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +0 -70
  139. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +0 -19
  140. data/lib/composite_primary_keys/dirty.rb +0 -19
  141. data/lib/composite_primary_keys/validations/uniqueness.rb +0 -41
  142. data/tasks/databases/oracle_enhanced.rake +0 -27
  143. data/tasks/databases/sqlite3.rake +0 -27
  144. data/test/connections/native_ibm_db/connection.rb +0 -19
  145. data/test/connections/native_mysql/connection.rb +0 -17
  146. data/test/connections/native_oracle/connection.rb +0 -11
  147. data/test/connections/native_oracle_enhanced/connection.rb +0 -16
  148. data/test/connections/native_postgresql/connection.rb +0 -13
  149. data/test/connections/native_sqlite3/connection.rb +0 -9
  150. data/test/connections/native_sqlserver/connection.rb +0 -11
  151. data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -92
  152. data/test/test_delete_all.rb +0 -35
  153. data/test/test_find_in_batches.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1f837ed1d8f5f9a5af46c14b91dfed1101e55de3
4
- data.tar.gz: e115fe2d97338b6d2aa19132be1f936f107dea74
2
+ SHA256:
3
+ metadata.gz: 133a4025b9fe7ee82617de7c3c34373d8f52d38d5e88c03ab742ebd954bf6064
4
+ data.tar.gz: 579e4d9e564e4c9e40f976d0d56b76533296c8f7e5b5ba925d7244141604fb08
5
5
  SHA512:
6
- metadata.gz: f81ee887e2a3145def527fbdce440bd2cc986fa2a03d4fef914e269e642ba355d09c307cb8be25723d6d79fed632fe238cd28376fb6734a549de54d7b9f16a2a
7
- data.tar.gz: 2e0166164b07de368e07758d72029c6461fab1596d311c11634b8c4e97dfd4159a3593d5acde2af2b60eec7701b7214f8487824b3b6185d687df064b5ebe91ef
6
+ metadata.gz: 334933952b9a84db67746c48c074c38d197215fa607640e134bf7aedd564e122a0c809318fab4529e0ad5bd181081baa792395419b25a4b19149066122cdfdfc
7
+ data.tar.gz: 2820381f390429bbdf61b0a04434c0432faa88d2cffdb04c5cd74f9dfc26682893809531b2d4dc14b03620614bec0ce1a69e128624b6a511b5718b19e24c9970
data/History.rdoc CHANGED
@@ -1,11 +1,62 @@
1
- == 8.1.6 (2017-05-20)
1
+ == 9.0.10 (2018-06-24)
2
2
 
3
- Query cache with bind params (ttw)
4
- Fix TestIds#test_set_ids_string. Sqlite's serial and integer are a bit different (Boris Peterbarg)
5
- Associations with inverse fix (Boris Peterbarg)
6
- Fix save_has_one_association and add a test for it (Boris Peterbarg)
7
- Fix save_belongs_to_association override (Boris Peterbarg)
8
- Extend approach from #344 to fix autosave for has_one associations as well (Cameron Finucane)
3
+ * Fix AR 5.0.7 (Jordan Owens)
4
+
5
+ == 9.0.9 (2018-03-06)
6
+
7
+ * Fix update statements that incorrectly pass NULL values for the primary key components (Sean Linsley)
8
+
9
+ == 9.0.8 (2017-10-11)
10
+
11
+ * Fix Paper Trail compatibility (Sean Linsley)
12
+
13
+ == 9.0.7 (2017-05-22)
14
+
15
+ * Update sqlite3 to support deletes and updates (Charlie Savage)
16
+ * Specify version for sql server gem so it works with Rails 5.0 (Charlie Savage)
17
+ * Use `datetime` datatype to address Invalid default value for updated_at (Yasuo Honda)
18
+ * Fix ORA-00900 error when it attempts to execute blank statement (pustomytnyk)
19
+ * Override ActiveRecord::Associations::CollectionAssociation#ids_reader (pustomytnyk)
20
+ * Only define #primary_keys if #primary_keys=(value) is called (Charlie Savage)
21
+ * Change `timestamp` to `datetime` for MySQL as ActiveRecord timestamps type does (Oriol Collel)
22
+ * Fix incorrect case statement to get PK for SQLServer (Oriol Collel)
23
+ * Fixes random failures in test_preload_of_polymorphic_association (Boris Peterbarg)
24
+
25
+ == 9.0.6 (2017-01-08)
26
+
27
+ * Uncomment tests (Sammy Larbi)
28
+ * Update readme (Charlie Savage)
29
+
30
+ == 9.0.5 (2017-01-02)
31
+
32
+ * Don't nest PK twice when looking up id, fixes #319 (Kerey Roper)
33
+ * Simplify database setup for tests (Charlie Savage)
34
+ * Revamp gem management (Charlie Savage)
35
+ * Add support for Relation#update_all when using joins (Charlie Savage)
36
+ * Add erb support to test database.yml files (Charlie Savage)
37
+ * Sqlserver fixes for ordering (Charlie Savage)
38
+ * Sqlserver refresh (Charlie Savage)
39
+ * Oracle refresh (Charlie Savage)
40
+ * Fix delete_all for MySql (Charlie Savage)
41
+ * Added test cases for preloading associations with and without conditions (Martin Körner)
42
+ * Revamp single association handling to correctly setup SQL binds (Charlie Savage)
43
+ * Remove references to ActiveModel - #352 (Charlie Savage)
44
+ * Fixes for #232, #359, #367 and #371 (Charlie Savage)
45
+
46
+ == 9.0.4 (2016-08-17)
47
+ * Do not set associations to readonly. See https://github.com/rails/rails/issues/24093 (Charlie Savage)
48
+
49
+ == 9.0.2 (2016-08-10)
50
+ * Fix delete_all when used with a join (Charlie Savage)
51
+
52
+ == 9.0.1 (2016-07-27)
53
+ * Create OR predicates in a nicely balanced tree fixing #320 (Nathan Samson)
54
+
55
+ == 9.0.0 (2016-07-06)
56
+ * Support connection_specification_name in rails5.0.0.rc1 (pocari)
57
+
58
+ == 9.0.0.beta1 (2016-04-16)
59
+ * Rails 5 beta support (Sammy Larbi)
9
60
 
10
61
  == 8.1.5 (2017-01-01)
11
62
 
@@ -38,6 +89,7 @@ Extend approach from #344 to fix autosave for has_one associations as well (Came
38
89
  * Remove call to verify_active_connections! which was removed from AR 4.1 (Steve Pletcher)
39
90
  * Aligned the establish connection paramater handling to be similar to latest version of rails (Harish Shetty)
40
91
 
92
+
41
93
  == 8.1.0 (2014-03-23)
42
94
 
43
95
  * ActiveRecord 4.2.1 support (Charlie Savage)
data/README.rdoc CHANGED
@@ -20,6 +20,7 @@ Every major version of ActiveRecord has included numerous internal changes. As
20
20
  CPK has to be rewritten for each version of ActiveRecord. To help keep
21
21
  things straight, here is the mapping:
22
22
 
23
+ Version 9.x is designed to work with ActiveRecord 5.0.x
23
24
  Version 8.x is designed to work with ActiveRecord 4.2.x
24
25
  Version 7.x is designed to work with ActiveRecord 4.1.x
25
26
  Version 6.x is designed to work with ActiveRecord 4.0.x
@@ -97,9 +98,69 @@ CPK supports the following databases:
97
98
 
98
99
  == Tests
99
100
 
101
+ To run tests you first need to install the appropriate gems for the database you want to test. Database gems are
102
+ divided into the following bundler groups:
103
+
104
+ * mysql
105
+ * oracle
106
+ * postgresql
107
+ * sqlite
108
+ * sqlserver
109
+
110
+ Since it is likely you do not have all the above databases installed on your computer, you want to install just the
111
+ gems for your database. For example, to test postgresql you would install the appropriate gems like this:
112
+
113
+ bundler install --without "mysql oracle sqlite sqlserver"
114
+
115
+ Once you have installed the appropriate gems, the next step is to create the test database. There is a rake
116
+ command for each database. Using our example:
117
+
118
+ rake postgresql:build_database
119
+
120
+ You can also rebuild the database if it already exists using this command:
121
+
122
+ rake postgresql:rebuild_database
123
+
124
+ To get a list of commands for your database use:
125
+
126
+ Rake -T
127
+
128
+ Finally, to run tests:
129
+
130
+ rake postgresql:test
131
+
100
132
  Travis build status: {<img src="https://travis-ci.org/composite-primary-keys/composite_primary_keys.svg" alt="Build Status" />}[https://travis-ci.org/composite-primary-keys/composite_primary_keys]
101
133
 
102
- See test/README_tests.rdoc for more information about running tests.
134
+ === DB2
135
+
136
+ DB2 is no longer supported due to difficulties in getting the ibm_db2 gem to build. Thus tests
137
+ have not been run against db2.
138
+
139
+ === MariaDb (mysql)
140
+
141
+ MariaDb is fully supported with all tests passing.
142
+
143
+ === Oracle
144
+
145
+ Oracle is fully supported with all tests passing.
146
+
147
+ === Postgresql
148
+
149
+ Postgresql is fully supported with all tests passing.
150
+
151
+ === Sqlite 3
152
+
153
+ The sqlite database is created at the path composite_primary_keys/db. Note you must *first* create the database using the
154
+ built-in rake task before running tests:
155
+
156
+ rake sqlite:build_database
157
+
158
+ Note not all tests currently pass on sqlite3. These failures happen when trying to DELETE records where the query
159
+ includes a JOIN.
160
+
161
+ === SqlServer
162
+
163
+ SqlServer is partially supported. There are a number of failing tests - patches welcomed.
103
164
 
104
165
  == Questions, Discussion and Contributions
105
166
 
data/Rakefile CHANGED
@@ -8,6 +8,9 @@ require 'rubygems/package_task'
8
8
  ::PROJECT_ROOT = File.expand_path(".")
9
9
  ::GEM_NAME = 'composite_primary_keys'
10
10
 
11
+ require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
12
+ require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
13
+
11
14
  # Read the spec file
12
15
  spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
13
16
 
@@ -20,7 +23,7 @@ Dir.glob('tasks/**/*.rake').each do |rake_file|
20
23
  end
21
24
 
22
25
  # Set up test tasks for each supported connection adapter
23
- %w(mysql sqlite3 oracle oracle_enhanced postgresql ibm_db sqlserver).each do |adapter|
26
+ %w(mysql sqlite oracle oracle_enhanced postgresql ibm_db sqlserver).each do |adapter|
24
27
  namespace adapter do
25
28
  desc "Run tests using the #{adapter} adapter"
26
29
  task "test" do
@@ -0,0 +1,6 @@
1
+ module CompositePrimaryKeys
2
+ module Nodes
3
+ class In < ::Arel::Nodes::Equality
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ module Arel
2
+ module Visitors
3
+ class SQLServer
4
+ def make_Fetch_Possible_And_Deterministic o
5
+ return if o.limit.nil? && o.offset.nil?
6
+ t = table_From_Statement o
7
+ pk = primary_Key_From_Table t
8
+ return unless pk
9
+ if o.orders.empty?
10
+ # Prefer deterministic vs a simple `(SELECT NULL)` expr.
11
+ # CPK
12
+ #o.orders = [pk.asc]
13
+ o.orders = pk.map {|a_pk| a_pk.asc}
14
+ end
15
+ end
16
+
17
+ def primary_Key_From_Table t
18
+ return unless t
19
+ column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.second.try(:name)
20
+
21
+ # CPK
22
+ # column_name ? t[column_name] : nil
23
+ case column_name
24
+ when Array
25
+ column_name.map do |name|
26
+ t[name]
27
+ end
28
+ when NilClass
29
+ nil
30
+ else
31
+ [t[column_name]]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module Arel
2
+ module Visitors
3
+ class ToSql
4
+ def visit_CompositePrimaryKeys_Nodes_In o, collector
5
+ collector << "("
6
+ visit(o.left, collector)
7
+ collector << ")"
8
+ collector << " IN ("
9
+ visit(o.right, collector) << ")"
10
+ end
11
+
12
+ def visit_CompositePrimaryKeys_CompositeKeys o, collector
13
+ values = o.map do |key|
14
+ case key
15
+ when Arel::Attributes::Attribute
16
+ "#{key.relation.name}.#{key.name}"
17
+ else
18
+ key
19
+ end
20
+ end
21
+ collector << "#{values.join(', ')}"
22
+ collector
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,22 +1,24 @@
1
1
  module ActiveRecord
2
2
  module Associations
3
3
  class Association
4
- def creation_attributes
5
- attributes = {}
4
+ silence_warnings do
5
+ def creation_attributes
6
+ attributes = {}
6
7
 
7
- if (reflection.has_one? || reflection.collection?) && !options[:through]
8
- # CPK
9
- # attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
10
- Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
11
- attributes[key1] = owner[key2]
12
- end
8
+ if (reflection.has_one? || reflection.collection?) && !options[:through]
9
+ # CPK
10
+ # attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
11
+ Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
12
+ attributes[key1] = owner[key2]
13
+ end
13
14
 
14
- if reflection.options[:as]
15
- attributes[reflection.type] = owner.class.base_class.name
15
+ if reflection.options[:as]
16
+ attributes[reflection.type] = owner.class.base_class.name
17
+ end
16
18
  end
17
- end
18
19
 
19
- attributes
20
+ attributes
21
+ end
20
22
  end
21
23
  end
22
24
  end
@@ -23,49 +23,44 @@ module ActiveRecord
23
23
  binds
24
24
  end
25
25
 
26
- def next_chain_scope(scope, table, reflection, tracker, assoc_klass, foreign_table, next_reflection)
27
- join_keys = reflection.join_keys(assoc_klass)
26
+ def last_chain_scope(scope, table, reflection, owner, association_klass)
27
+ join_keys = reflection.join_keys(association_klass)
28
28
  key = join_keys.key
29
29
  foreign_key = join_keys.foreign_key
30
30
 
31
31
  # CPK
32
- # constraint = table[key].eq(foreign_table[foreign_key])
33
- constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
32
+ #value = transform_value(owner[foreign_key])
33
+ #scope = scope.where(table.name => { key => value })
34
+ mappings = Array(key).zip(Array(foreign_key))
35
+ joins = mappings.reduce(Hash.new) do |hash, mapping|
36
+ hash[mapping.first] = transform_value(owner[mapping.last])
37
+ hash
38
+ end
39
+ scope = scope.where(table.name => joins)
34
40
 
35
41
  if reflection.type
36
- value = next_reflection.klass.base_class.name
37
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
38
- scope = scope.where(table[reflection.type].eq(bind_val))
42
+ polymorphic_type = transform_value(owner.class.base_class.name)
43
+ scope = scope.where(table.name => { reflection.type => polymorphic_type })
39
44
  end
40
45
 
41
- scope.joins(join(foreign_table, constraint))
46
+ scope
42
47
  end
43
48
 
44
- def last_chain_scope(scope, table, reflection, owner, tracker, assoc_klass)
45
- join_keys = reflection.join_keys(assoc_klass)
49
+ def next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
50
+ join_keys = reflection.join_keys(association_klass)
46
51
  key = join_keys.key
47
52
  foreign_key = join_keys.foreign_key
48
53
 
49
- if key.kind_of?(Array) || foreign_key.kind_of?(Array)
50
- key = Array(key) unless key.kind_of?(Array)
51
- foreign_key = Array(foreign_key) unless foreign_key.kind_of?(Array)
52
- key.zip(foreign_key).map do |k, fk|
53
- bind_val = bind scope, table.table_name, k.to_s, owner[fk], tracker
54
- scope = scope.where(table[k].eq(bind_val))
55
- end
56
- else
57
- bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
58
- scope = scope.where(table[key].eq(bind_val))
59
- end
54
+ # CPK
55
+ # constraint = table[key].eq(foreign_table[foreign_key])
56
+ constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
60
57
 
61
58
  if reflection.type
62
- value = owner.class.base_class.name
63
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
64
-
65
- scope.where(table[reflection.type].eq(bind_val))
66
- else
67
- scope
59
+ value = transform_value(next_reflection.klass.base_class.name)
60
+ scope = scope.where(table.name => { reflection.type => value })
68
61
  end
62
+
63
+ scope = scope.joins(join(foreign_table, constraint))
69
64
  end
70
65
  end
71
66
  end
@@ -1,15 +1,46 @@
1
1
  module CompositePrimaryKeys
2
2
  module CollectionAssociation
3
- extend ActiveSupport::Concern
4
- included do
5
- def get_records_with_cpk_support
6
- cpk_applies = (target && target.respond_to?(:composite?) && target.composite?) || (owner && owner.respond_to?(:composite?) && owner.composite?)
7
- return scope.to_a if cpk_applies
8
- get_records_without_cpk_support
3
+ def get_records
4
+ cpk_applies = target.try(:composite?) || owner.try(:composite?)
5
+ return scope.to_a if cpk_applies
6
+ super
7
+ end
8
+
9
+ def ids_reader
10
+ if loaded?
11
+ load_target.map do |record|
12
+ if reflection.association_primary_key.is_a?(Array)
13
+ reflection.association_primary_key.map { |key| record.send(key) }
14
+ else
15
+ record.send(reflection.association_primary_key)
16
+ end
17
+ end
18
+ else
19
+ @association_ids ||= (
20
+ column = "#{reflection.quoted_table_name}.#{reflection.association_primary_key}"
21
+ scope.pluck(column)
22
+ )
23
+ end
24
+ end
25
+
26
+ def ids_writer(ids)
27
+ pk_type = reflection.primary_key_type
28
+ ids = Array(ids).reject(&:blank?)
29
+ ids.map! { |i| pk_type.cast(i) }
30
+ # CPK
31
+ if reflection.association_primary_key.is_a?(Array)
32
+ predicate = Class.new.extend(CompositePrimaryKeys::Predicates).cpk_in_predicate(klass.arel_table, reflection.association_primary_key, ids)
33
+ records = klass.where(predicate).index_by do |r|
34
+ reflection.association_primary_key.map{ |k| r.send(k) }
35
+ end.values_at(*ids)
36
+ else
37
+ records = klass.where(reflection.association_primary_key => ids).index_by do |r|
38
+ r.send(reflection.association_primary_key)
39
+ end.values_at(*ids)
9
40
  end
10
- alias_method_chain :get_records, :cpk_support
41
+ replace(records)
11
42
  end
12
43
  end
13
44
  end
14
45
 
15
- ActiveRecord::Associations::CollectionAssociation.send(:include, CompositePrimaryKeys::CollectionAssociation)
46
+ ActiveRecord::Associations::CollectionAssociation.prepend CompositePrimaryKeys::CollectionAssociation
@@ -1,6 +1,23 @@
1
1
  module ActiveRecord
2
2
  module Associations
3
3
  class HasManyAssociation
4
+ include CompositePrimaryKeys::Predicates
5
+
6
+ def delete_records(records, method)
7
+ if method == :destroy
8
+ records.each(&:destroy!)
9
+ update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
10
+ return
11
+ # Zerista
12
+ elsif self.reflection.klass.composite?
13
+ predicate = cpk_in_predicate(self.scope.table, self.reflection.klass.primary_keys, records.map(&:id))
14
+ scope = self.scope.where(predicate)
15
+ else
16
+ scope = self.scope.where(reflection.klass.primary_key => records)
17
+ end
18
+ update_counter(-delete_count(method, scope))
19
+ end
20
+
4
21
  def delete_count(method, scope)
5
22
  if method == :delete_all
6
23
  scope.delete_all
@@ -15,46 +32,6 @@ module ActiveRecord
15
32
  end
16
33
  end
17
34
 
18
- def delete_records(records, method)
19
- if method == :destroy
20
- records.each(&:destroy!)
21
- update_counter(-records.length) unless inverse_updates_counter_cache?
22
- else
23
- if records == :all || !reflection.klass.primary_key
24
- scope = self.scope
25
- else
26
- # CPK
27
- # scope = self.scope.where(reflection.klass.primary_key => records)
28
- table = Arel::Table.new(reflection.table_name)
29
- and_conditions = records.map do |record|
30
- eq_conditions = Array(reflection.association_primary_key).map do |name|
31
- table[name].eq(record[name])
32
- end
33
- Arel::Nodes::And.new(eq_conditions)
34
- end
35
-
36
- condition = and_conditions.shift
37
- and_conditions.each do |and_condition|
38
- condition = condition.or(and_condition)
39
- end
40
-
41
- scope = self.scope.where(condition)
42
- end
43
-
44
- if method == :delete_all
45
- update_counter(-scope.delete_all)
46
- else
47
- # CPK
48
- # update_counter(-scope.update_all(reflection.foreign_key => nil))
49
- update_hash = Array(reflection.foreign_key).inject(Hash.new) do |hash, key|
50
- hash[key] = nil
51
- hash
52
- end
53
- update_counter(-scope.update_all(update_hash))
54
- end
55
- end
56
- end
57
-
58
35
  def foreign_key_present?
59
36
  if reflection.klass.primary_key
60
37
  # CPK
@@ -13,79 +13,79 @@ module ActiveRecord
13
13
  cpk_in_predicate(through_association.scope.klass.arel_table, source_reflection.foreign_key, ids)
14
14
  end
15
15
 
16
- def delete_records(records, method)
17
- ensure_not_nested
16
+ silence_warnings do
17
+ def delete_records(records, method)
18
+ ensure_not_nested
18
19
 
19
- scope = through_association.scope
20
- # CPK
21
- # scope.where! construct_join_attributes(*records)
22
- source_klass = source_reflection.polymorphic? ? klass : source_reflection.klass
23
- if source_klass.composite?
24
- scope.where! cpk_join_through_predicate(*records)
25
- else
26
- scope.where! construct_join_attributes(*records)
27
- end
28
-
29
- case method
30
- when :destroy
31
- if scope.klass.primary_key
32
- count = scope.destroy_all.length
20
+ scope = through_association.scope
21
+ # CPK
22
+ # scope.where! construct_join_attributes(*records)
23
+ if source_reflection.klass.composite?
24
+ scope.where! cpk_join_through_predicate(*records)
33
25
  else
34
- scope.to_a.each do |record|
35
- record.run_callbacks :destroy
36
- end
26
+ scope.where! construct_join_attributes(*records)
27
+ end
37
28
 
38
- arel = scope.arel
29
+ case method
30
+ when :destroy
31
+ if scope.klass.primary_key
32
+ count = scope.destroy_all.length
33
+ else
34
+ scope.to_a.each do |record|
35
+ record.run_callbacks :destroy
36
+ end
39
37
 
40
- stmt = Arel::DeleteManager.new arel.engine
41
- stmt.from scope.klass.arel_table
42
- stmt.wheres = arel.constraints
38
+ arel = scope.arel
43
39
 
44
- count = scope.klass.connection.delete(stmt, 'SQL', scope.bind_values)
40
+ stmt = Arel::DeleteManager.new arel.engine
41
+ stmt.from scope.klass.arel_table
42
+ stmt.wheres = arel.constraints
43
+
44
+ count = scope.klass.connection.delete(stmt, 'SQL', scope.bind_values)
45
+ end
46
+ when :nullify
47
+ count = scope.update_all(source_reflection.foreign_key => nil)
48
+ else
49
+ count = scope.delete_all
45
50
  end
46
- when :nullify
47
- count = scope.update_all(source_reflection.foreign_key => nil)
48
- else
49
- count = scope.delete_all
50
- end
51
51
 
52
- delete_through_records(records)
52
+ delete_through_records(records)
53
53
 
54
- if source_reflection.options[:counter_cache] && method != :destroy
55
- counter = source_reflection.counter_cache_column
56
- klass.decrement_counter counter, records.map(&:id)
57
- end
54
+ if source_reflection.options[:counter_cache] && method != :destroy
55
+ counter = source_reflection.counter_cache_column
56
+ klass.decrement_counter counter, records.map(&:id)
57
+ end
58
58
 
59
- if through_reflection.collection? && update_through_counter?(method)
60
- update_counter(-count, through_reflection)
61
- end
59
+ if through_reflection.collection? && update_through_counter?(method)
60
+ update_counter(-count, through_reflection)
61
+ end
62
62
 
63
- update_counter(-count)
64
- end
63
+ update_counter(-count)
64
+ end
65
65
 
66
- def through_records_for(record)
67
- # CPK
68
- # attributes = construct_join_attributes(record)
69
- # candidates = Array.wrap(through_association.target)
70
- # candidates.find_all do |c|
71
- # attributes.all? do |key, value|
72
- # c.public_send(key) == value
73
- # end
74
- # end
75
- if record.composite?
76
- candidates = Array.wrap(through_association.target)
77
- candidates.find_all { |c| c.attributes.slice(*source_reflection.association_primary_key) == record.ids_hash }
78
- else
79
- attributes = construct_join_attributes(record)
80
- candidates = Array.wrap(through_association.target)
81
- candidates.find_all do |c|
82
- attributes.all? do |key, value|
83
- c.public_send(key) == value
66
+ def through_records_for(record)
67
+ # CPK
68
+ # attributes = construct_join_attributes(record)
69
+ # candidates = Array.wrap(through_association.target)
70
+ # candidates.find_all do |c|
71
+ # attributes.all? do |key, value|
72
+ # c.public_send(key) == value
73
+ # end
74
+ # end
75
+ if record.composite?
76
+ candidates = Array.wrap(through_association.target)
77
+ candidates.find_all { |c| c.attributes.slice(*source_reflection.association_primary_key) == record.ids_hash }
78
+ else
79
+ attributes = construct_join_attributes(record)
80
+ candidates = Array.wrap(through_association.target)
81
+ candidates.find_all do |c|
82
+ attributes.all? do |key, value|
83
+ c.public_send(key) == value
84
+ end
84
85
  end
85
86
  end
86
87
  end
87
88
  end
88
-
89
89
  end
90
90
  end
91
91
  end
@@ -2,19 +2,21 @@ module ActiveRecord
2
2
  module Associations
3
3
  class JoinDependency
4
4
  class JoinAssociation
5
- def build_constraint(klass, table, key, foreign_table, foreign_key)
6
- # CPK
7
- # constraint = table[key].eq(foreign_table[foreign_key])
8
- constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
5
+ silence_warnings do
6
+ def build_constraint(klass, table, key, foreign_table, foreign_key)
7
+ # CPK
8
+ # constraint = table[key].eq(foreign_table[foreign_key])
9
+ constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
9
10
 
10
- if klass.finder_needs_type_condition?
11
- constraint = table.create_and([
12
- constraint,
13
- klass.send(:type_condition, table)
14
- ])
15
- end
11
+ if klass.finder_needs_type_condition?
12
+ constraint = table.create_and([
13
+ constraint,
14
+ klass.send(:type_condition, table)
15
+ ])
16
+ end
16
17
 
17
- constraint
18
+ constraint
19
+ end
18
20
  end
19
21
  end
20
22
  end