activerecord 3.2.22.4 → 4.0.13

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2799 -617
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +23 -32
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +40 -34
  7. data/lib/active_record/association_relation.rb +22 -0
  8. data/lib/active_record/associations/alias_tracker.rb +4 -2
  9. data/lib/active_record/associations/association.rb +60 -46
  10. data/lib/active_record/associations/association_scope.rb +46 -40
  11. data/lib/active_record/associations/belongs_to_association.rb +17 -4
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +73 -56
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +130 -96
  21. data/lib/active_record/associations/collection_proxy.rb +916 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
  23. data/lib/active_record/associations/has_many_association.rb +35 -8
  24. data/lib/active_record/associations/has_many_through_association.rb +37 -17
  25. data/lib/active_record/associations/has_one_association.rb +42 -19
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
  28. data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
  29. data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
  30. data/lib/active_record/associations/join_dependency.rb +30 -9
  31. data/lib/active_record/associations/join_helper.rb +1 -11
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
  35. data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/preloader.rb +20 -43
  39. data/lib/active_record/associations/singular_association.rb +11 -11
  40. data/lib/active_record/associations/through_association.rb +3 -3
  41. data/lib/active_record/associations.rb +223 -282
  42. data/lib/active_record/attribute_assignment.rb +134 -154
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  44. data/lib/active_record/attribute_methods/dirty.rb +36 -29
  45. data/lib/active_record/attribute_methods/primary_key.rb +45 -31
  46. data/lib/active_record/attribute_methods/query.rb +5 -4
  47. data/lib/active_record/attribute_methods/read.rb +67 -90
  48. data/lib/active_record/attribute_methods/serialization.rb +133 -70
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
  50. data/lib/active_record/attribute_methods/write.rb +34 -39
  51. data/lib/active_record/attribute_methods.rb +268 -108
  52. data/lib/active_record/autosave_association.rb +80 -73
  53. data/lib/active_record/base.rb +54 -451
  54. data/lib/active_record/callbacks.rb +60 -22
  55. data/lib/active_record/coders/yaml_column.rb +18 -21
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
  67. data/lib/active_record/connection_adapters/column.rb +67 -36
  68. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
  70. data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
  71. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
  72. data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
  73. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
  75. data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
  76. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  77. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
  78. data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
  79. data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
  80. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
  81. data/lib/active_record/connection_handling.rb +98 -0
  82. data/lib/active_record/core.rb +472 -0
  83. data/lib/active_record/counter_cache.rb +107 -108
  84. data/lib/active_record/dynamic_matchers.rb +115 -63
  85. data/lib/active_record/errors.rb +36 -18
  86. data/lib/active_record/explain.rb +15 -63
  87. data/lib/active_record/explain_registry.rb +30 -0
  88. data/lib/active_record/explain_subscriber.rb +8 -4
  89. data/lib/active_record/fixture_set/file.rb +55 -0
  90. data/lib/active_record/fixtures.rb +159 -155
  91. data/lib/active_record/inheritance.rb +93 -59
  92. data/lib/active_record/integration.rb +8 -8
  93. data/lib/active_record/locale/en.yml +8 -1
  94. data/lib/active_record/locking/optimistic.rb +39 -43
  95. data/lib/active_record/locking/pessimistic.rb +4 -4
  96. data/lib/active_record/log_subscriber.rb +19 -9
  97. data/lib/active_record/migration/command_recorder.rb +102 -33
  98. data/lib/active_record/migration/join_table.rb +15 -0
  99. data/lib/active_record/migration.rb +411 -173
  100. data/lib/active_record/model_schema.rb +81 -94
  101. data/lib/active_record/nested_attributes.rb +173 -131
  102. data/lib/active_record/null_relation.rb +67 -0
  103. data/lib/active_record/persistence.rb +254 -106
  104. data/lib/active_record/query_cache.rb +18 -36
  105. data/lib/active_record/querying.rb +19 -15
  106. data/lib/active_record/railtie.rb +113 -38
  107. data/lib/active_record/railties/console_sandbox.rb +3 -4
  108. data/lib/active_record/railties/controller_runtime.rb +4 -3
  109. data/lib/active_record/railties/databases.rake +115 -368
  110. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  111. data/lib/active_record/readonly_attributes.rb +7 -3
  112. data/lib/active_record/reflection.rb +110 -61
  113. data/lib/active_record/relation/batches.rb +29 -29
  114. data/lib/active_record/relation/calculations.rb +155 -125
  115. data/lib/active_record/relation/delegation.rb +94 -18
  116. data/lib/active_record/relation/finder_methods.rb +151 -203
  117. data/lib/active_record/relation/merger.rb +188 -0
  118. data/lib/active_record/relation/predicate_builder.rb +85 -42
  119. data/lib/active_record/relation/query_methods.rb +793 -146
  120. data/lib/active_record/relation/spawn_methods.rb +43 -150
  121. data/lib/active_record/relation.rb +293 -173
  122. data/lib/active_record/result.rb +48 -7
  123. data/lib/active_record/runtime_registry.rb +17 -0
  124. data/lib/active_record/sanitization.rb +41 -54
  125. data/lib/active_record/schema.rb +19 -12
  126. data/lib/active_record/schema_dumper.rb +41 -41
  127. data/lib/active_record/schema_migration.rb +46 -0
  128. data/lib/active_record/scoping/default.rb +56 -52
  129. data/lib/active_record/scoping/named.rb +78 -103
  130. data/lib/active_record/scoping.rb +54 -124
  131. data/lib/active_record/serialization.rb +6 -2
  132. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  133. data/lib/active_record/statement_cache.rb +26 -0
  134. data/lib/active_record/store.rb +131 -15
  135. data/lib/active_record/tasks/database_tasks.rb +204 -0
  136. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  137. data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
  138. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  139. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  140. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  141. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  142. data/lib/active_record/test_case.rb +67 -38
  143. data/lib/active_record/timestamp.rb +16 -11
  144. data/lib/active_record/transactions.rb +73 -51
  145. data/lib/active_record/validations/associated.rb +19 -13
  146. data/lib/active_record/validations/presence.rb +65 -0
  147. data/lib/active_record/validations/uniqueness.rb +110 -57
  148. data/lib/active_record/validations.rb +18 -17
  149. data/lib/active_record/version.rb +7 -6
  150. data/lib/active_record.rb +63 -45
  151. data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
  152. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
  153. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  154. data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
  155. data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
  156. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  157. data/lib/rails/generators/active_record.rb +3 -5
  158. metadata +43 -29
  159. data/examples/associations.png +0 -0
  160. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  161. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  162. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  163. data/lib/active_record/dynamic_finder_match.rb +0 -68
  164. data/lib/active_record/dynamic_scope_match.rb +0 -23
  165. data/lib/active_record/fixtures/file.rb +0 -65
  166. data/lib/active_record/identity_map.rb +0 -162
  167. data/lib/active_record/observer.rb +0 -121
  168. data/lib/active_record/session_store.rb +0 -360
  169. data/lib/rails/generators/active_record/migration.rb +0 -15
  170. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  171. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  172. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  173. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,180 +1,73 @@
1
- require 'active_support/core_ext/object/blank'
1
+ require 'active_support/core_ext/hash/except'
2
+ require 'active_support/core_ext/hash/slice'
3
+ require 'active_record/relation/merger'
2
4
 
3
5
  module ActiveRecord
4
6
  module SpawnMethods
5
- def merge(r)
6
- return self unless r
7
- return to_a & r if r.is_a?(Array)
8
7
 
9
- merged_relation = clone
10
-
11
- r = r.with_default_scope if r.default_scoped? && r.klass != klass
12
-
13
- Relation::ASSOCIATION_METHODS.each do |method|
14
- value = r.send(:"#{method}_values")
15
-
16
- unless value.empty?
17
- if method == :includes
18
- merged_relation = merged_relation.includes(value)
19
- else
20
- merge_relation_method(merged_relation, method, value)
21
- end
22
- end
23
- end
24
-
25
- (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
26
- value = r.send(:"#{method}_values")
27
- merge_relation_method(merged_relation, method, value) if value.present?
28
- end
29
-
30
- merge_joins(merged_relation, r)
31
-
32
- merged_wheres = @where_values + r.where_values
33
-
34
- unless @where_values.empty?
35
- # Remove duplicate ARel attributes. Last one wins.
36
- seen = Hash.new { |h,table| h[table] = {} }
37
- merged_wheres = merged_wheres.reverse.reject { |w|
38
- nuke = false
39
- if w.respond_to?(:operator) && w.operator == :== &&
40
- w.left.respond_to?(:relation)
41
- name = w.left.name
42
- table = w.left.relation.name
43
- nuke = seen[table][name]
44
- seen[table][name] = true
45
- end
46
- nuke
47
- }.reverse
48
- end
49
-
50
- merged_relation.where_values = merged_wheres
8
+ # This is overridden by Associations::CollectionProxy
9
+ def spawn #:nodoc:
10
+ clone
11
+ end
51
12
 
52
- (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
53
- value = r.send(:"#{method}_value")
54
- merged_relation.send(:"#{method}_value=", value) unless value.nil?
13
+ # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an <tt>ActiveRecord::Relation</tt>.
14
+ # Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array.
15
+ # Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
16
+ # # Performs a single join query with both where conditions.
17
+ #
18
+ # recent_posts = Post.order('created_at DESC').first(5)
19
+ # Post.where(published: true).merge(recent_posts)
20
+ # # Returns the intersection of all published posts with the 5 most recently created posts.
21
+ # # (This is just an example. You'd probably want to do this with a single query!)
22
+ #
23
+ # Procs will be evaluated by merge:
24
+ #
25
+ # Post.where(published: true).merge(-> { joins(:comments) })
26
+ # # => Post.where(published: true).joins(:comments)
27
+ #
28
+ # This is mainly intended for sharing common conditions between multiple associations.
29
+ def merge(other)
30
+ if other.is_a?(Array)
31
+ to_a & other
32
+ elsif other
33
+ spawn.merge!(other)
34
+ else
35
+ self
55
36
  end
37
+ end
56
38
 
57
- merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
58
-
59
- merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
60
-
61
- if (r.reordering_value)
62
- # override any order specified in the original relation
63
- merged_relation.reordering_value = true
64
- merged_relation.order_values = r.order_values
39
+ def merge!(other) # :nodoc:
40
+ if !other.is_a?(Relation) && other.respond_to?(:to_proc)
41
+ instance_exec(&other)
65
42
  else
66
- # merge in order_values from r
67
- merged_relation.order_values += r.order_values
43
+ klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger
44
+ klass.new(self, other).merge
68
45
  end
69
-
70
- # Apply scope extension modules
71
- merged_relation.send :apply_modules, r.extensions
72
-
73
- merged_relation
74
46
  end
75
47
 
76
48
  # Removes from the query the condition(s) specified in +skips+.
77
49
  #
78
- # Example:
79
- #
80
50
  # Post.order('id asc').except(:order) # discards the order condition
81
51
  # Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
82
- #
83
52
  def except(*skips)
84
- result = self.class.new(@klass, table)
85
- result.default_scoped = default_scoped
86
-
87
- ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
88
- result.send(:"#{method}_values=", send(:"#{method}_values"))
89
- end
90
-
91
- (Relation::SINGLE_VALUE_METHODS - skips).each do |method|
92
- result.send(:"#{method}_value=", send(:"#{method}_value"))
93
- end
94
-
95
- # Apply scope extension modules
96
- result.send(:apply_modules, extensions)
97
-
98
- result
53
+ relation_with values.except(*skips)
99
54
  end
100
55
 
101
56
  # Removes any condition from the query other than the one(s) specified in +onlies+.
102
57
  #
103
- # Example:
104
- #
105
58
  # Post.order('id asc').only(:where) # discards the order condition
106
59
  # Post.order('id asc').only(:where, :order) # uses the specified order
107
- #
108
60
  def only(*onlies)
109
- result = self.class.new(@klass, table)
110
- result.default_scoped = default_scoped
111
-
112
- ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
113
- result.send(:"#{method}_values=", send(:"#{method}_values"))
114
- end
115
-
116
- (Relation::SINGLE_VALUE_METHODS & onlies).each do |method|
117
- result.send(:"#{method}_value=", send(:"#{method}_value"))
118
- end
119
-
120
- # Apply scope extension modules
121
- result.send(:apply_modules, extensions)
122
-
123
- result
124
- end
125
-
126
- VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
127
- :order, :select, :readonly, :group, :having, :from, :lock ]
128
-
129
- def apply_finder_options(options)
130
- relation = clone
131
- return relation unless options
132
-
133
- options.assert_valid_keys(VALID_FIND_OPTIONS)
134
- finders = options.dup
135
- finders.delete_if { |key, value| value.nil? && key != :limit }
136
-
137
- ([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
138
- relation = relation.send(finder, finders[finder])
139
- end
140
-
141
- relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
142
- relation = relation.includes(finders[:include]) if options.has_key?(:include)
143
- relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
144
-
145
- relation
61
+ relation_with values.slice(*onlies)
146
62
  end
147
63
 
148
64
  private
149
65
 
150
- def merge_joins(relation, other)
151
- values = other.joins_values
152
- return if values.blank?
153
-
154
- if other.klass >= relation.klass
155
- relation.joins_values += values
156
- else
157
- joins_dependency, rest = values.partition do |join|
158
- case join
159
- when Hash, Symbol, Array
160
- true
161
- else
162
- false
163
- end
164
- end
165
-
166
- join_dependency = ActiveRecord::Associations::JoinDependency.new(
167
- other.klass,
168
- joins_dependency,
169
- []
170
- )
171
-
172
- relation.joins_values += join_dependency.join_associations + rest
173
- end
174
- end
175
-
176
- def merge_relation_method(relation, method, value)
177
- relation.send(:"#{method}_values=", relation.send(:"#{method}_values") + value)
66
+ def relation_with(values) # :nodoc:
67
+ result = Relation.new(klass, table, values)
68
+ result.default_scoped = default_scoped
69
+ result.extend(*extending_values) if extending_values.any?
70
+ result
178
71
  end
179
72
  end
180
73
  end