activerecord 4.1.8 → 4.2.11.3

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 (186) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1165 -1591
  3. data/README.rdoc +15 -10
  4. data/lib/active_record/aggregations.rb +15 -8
  5. data/lib/active_record/association_relation.rb +13 -0
  6. data/lib/active_record/associations/alias_tracker.rb +3 -12
  7. data/lib/active_record/associations/association.rb +16 -4
  8. data/lib/active_record/associations/association_scope.rb +84 -43
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -10
  10. data/lib/active_record/associations/builder/association.rb +16 -5
  11. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  12. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  13. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -14
  14. data/lib/active_record/associations/builder/has_many.rb +1 -1
  15. data/lib/active_record/associations/builder/has_one.rb +2 -2
  16. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  17. data/lib/active_record/associations/collection_association.rb +87 -30
  18. data/lib/active_record/associations/collection_proxy.rb +33 -35
  19. data/lib/active_record/associations/foreign_association.rb +11 -0
  20. data/lib/active_record/associations/has_many_association.rb +83 -22
  21. data/lib/active_record/associations/has_many_through_association.rb +49 -26
  22. data/lib/active_record/associations/has_one_association.rb +1 -1
  23. data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
  24. data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
  25. data/lib/active_record/associations/join_dependency.rb +26 -12
  26. data/lib/active_record/associations/preloader/association.rb +14 -10
  27. data/lib/active_record/associations/preloader/through_association.rb +4 -3
  28. data/lib/active_record/associations/preloader.rb +37 -26
  29. data/lib/active_record/associations/singular_association.rb +17 -2
  30. data/lib/active_record/associations/through_association.rb +16 -12
  31. data/lib/active_record/associations.rb +158 -49
  32. data/lib/active_record/attribute.rb +163 -0
  33. data/lib/active_record/attribute_assignment.rb +20 -12
  34. data/lib/active_record/attribute_decorators.rb +66 -0
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  36. data/lib/active_record/attribute_methods/dirty.rb +107 -43
  37. data/lib/active_record/attribute_methods/primary_key.rb +7 -8
  38. data/lib/active_record/attribute_methods/query.rb +1 -1
  39. data/lib/active_record/attribute_methods/read.rb +22 -59
  40. data/lib/active_record/attribute_methods/serialization.rb +16 -150
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -28
  42. data/lib/active_record/attribute_methods/write.rb +9 -24
  43. data/lib/active_record/attribute_methods.rb +57 -95
  44. data/lib/active_record/attribute_set/builder.rb +106 -0
  45. data/lib/active_record/attribute_set.rb +81 -0
  46. data/lib/active_record/attributes.rb +147 -0
  47. data/lib/active_record/autosave_association.rb +30 -12
  48. data/lib/active_record/base.rb +13 -24
  49. data/lib/active_record/callbacks.rb +6 -6
  50. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +85 -53
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +139 -57
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +271 -74
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -60
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +295 -141
  62. data/lib/active_record/connection_adapters/column.rb +29 -240
  63. data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
  64. data/lib/active_record/connection_adapters/mysql2_adapter.rb +17 -33
  65. data/lib/active_record/connection_adapters/mysql_adapter.rb +68 -145
  66. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  67. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  68. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
  69. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -385
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  97. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  98. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +134 -43
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
  101. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
  103. data/lib/active_record/connection_handling.rb +1 -1
  104. data/lib/active_record/core.rb +163 -40
  105. data/lib/active_record/counter_cache.rb +60 -6
  106. data/lib/active_record/enum.rb +10 -12
  107. data/lib/active_record/errors.rb +53 -30
  108. data/lib/active_record/explain.rb +1 -1
  109. data/lib/active_record/explain_subscriber.rb +1 -1
  110. data/lib/active_record/fixtures.rb +62 -74
  111. data/lib/active_record/gem_version.rb +4 -4
  112. data/lib/active_record/inheritance.rb +35 -10
  113. data/lib/active_record/integration.rb +4 -4
  114. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  115. data/lib/active_record/locking/optimistic.rb +46 -26
  116. data/lib/active_record/migration/command_recorder.rb +19 -2
  117. data/lib/active_record/migration/join_table.rb +1 -1
  118. data/lib/active_record/migration.rb +79 -47
  119. data/lib/active_record/model_schema.rb +52 -58
  120. data/lib/active_record/nested_attributes.rb +18 -8
  121. data/lib/active_record/no_touching.rb +1 -1
  122. data/lib/active_record/persistence.rb +48 -27
  123. data/lib/active_record/query_cache.rb +3 -3
  124. data/lib/active_record/querying.rb +10 -7
  125. data/lib/active_record/railtie.rb +19 -14
  126. data/lib/active_record/railties/databases.rake +55 -56
  127. data/lib/active_record/readonly_attributes.rb +0 -1
  128. data/lib/active_record/reflection.rb +281 -117
  129. data/lib/active_record/relation/batches.rb +0 -1
  130. data/lib/active_record/relation/calculations.rb +41 -37
  131. data/lib/active_record/relation/delegation.rb +1 -1
  132. data/lib/active_record/relation/finder_methods.rb +71 -48
  133. data/lib/active_record/relation/merger.rb +39 -29
  134. data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
  135. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  136. data/lib/active_record/relation/predicate_builder.rb +42 -12
  137. data/lib/active_record/relation/query_methods.rb +130 -73
  138. data/lib/active_record/relation/spawn_methods.rb +10 -3
  139. data/lib/active_record/relation.rb +57 -25
  140. data/lib/active_record/result.rb +18 -7
  141. data/lib/active_record/sanitization.rb +12 -2
  142. data/lib/active_record/schema.rb +0 -1
  143. data/lib/active_record/schema_dumper.rb +59 -28
  144. data/lib/active_record/schema_migration.rb +5 -4
  145. data/lib/active_record/scoping/default.rb +6 -4
  146. data/lib/active_record/scoping/named.rb +4 -0
  147. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  148. data/lib/active_record/statement_cache.rb +95 -10
  149. data/lib/active_record/store.rb +5 -5
  150. data/lib/active_record/tasks/database_tasks.rb +61 -8
  151. data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
  152. data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
  153. data/lib/active_record/timestamp.rb +9 -7
  154. data/lib/active_record/transactions.rb +54 -28
  155. data/lib/active_record/type/big_integer.rb +13 -0
  156. data/lib/active_record/type/binary.rb +50 -0
  157. data/lib/active_record/type/boolean.rb +31 -0
  158. data/lib/active_record/type/date.rb +50 -0
  159. data/lib/active_record/type/date_time.rb +54 -0
  160. data/lib/active_record/type/decimal.rb +64 -0
  161. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  162. data/lib/active_record/type/decorator.rb +14 -0
  163. data/lib/active_record/type/float.rb +19 -0
  164. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  165. data/lib/active_record/type/integer.rb +59 -0
  166. data/lib/active_record/type/mutable.rb +16 -0
  167. data/lib/active_record/type/numeric.rb +36 -0
  168. data/lib/active_record/type/serialized.rb +62 -0
  169. data/lib/active_record/type/string.rb +40 -0
  170. data/lib/active_record/type/text.rb +11 -0
  171. data/lib/active_record/type/time.rb +26 -0
  172. data/lib/active_record/type/time_value.rb +38 -0
  173. data/lib/active_record/type/type_map.rb +64 -0
  174. data/lib/active_record/type/unsigned_integer.rb +15 -0
  175. data/lib/active_record/type/value.rb +110 -0
  176. data/lib/active_record/type.rb +23 -0
  177. data/lib/active_record/validations/associated.rb +5 -3
  178. data/lib/active_record/validations/presence.rb +5 -3
  179. data/lib/active_record/validations/uniqueness.rb +24 -20
  180. data/lib/active_record/validations.rb +25 -19
  181. data/lib/active_record.rb +5 -0
  182. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  183. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  184. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  185. metadata +66 -11
  186. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,20 +1,7 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
- class Transaction #:nodoc:
4
- attr_reader :connection
5
-
6
- def initialize(connection)
7
- @connection = connection
8
- @state = TransactionState.new
9
- end
10
-
11
- def state
12
- @state
13
- end
14
- end
15
-
16
3
  class TransactionState
17
- attr_accessor :parent
4
+ attr_reader :parent
18
5
 
19
6
  VALID_STATES = Set.new([:committed, :rolledback, nil])
20
7
 
@@ -35,6 +22,10 @@ module ActiveRecord
35
22
  @state == :rolledback
36
23
  end
37
24
 
25
+ def completed?
26
+ committed? || rolledback?
27
+ end
28
+
38
29
  def set_state(state)
39
30
  if !VALID_STATES.include?(state)
40
31
  raise ArgumentError, "Invalid transaction state: #{state}"
@@ -43,127 +34,106 @@ module ActiveRecord
43
34
  end
44
35
  end
45
36
 
46
- class ClosedTransaction < Transaction #:nodoc:
47
- def number
48
- 0
49
- end
50
-
51
- def begin(options = {})
52
- RealTransaction.new(connection, self, options)
53
- end
54
-
55
- def closed?
56
- true
57
- end
58
-
59
- def open?
60
- false
61
- end
62
-
63
- def joinable?
64
- false
65
- end
66
-
67
- # This is a noop when there are no open transactions
68
- def add_record(record)
69
- end
37
+ class NullTransaction #:nodoc:
38
+ def initialize; end
39
+ def closed?; true; end
40
+ def open?; false; end
41
+ def joinable?; false; end
42
+ def add_record(record); end
70
43
  end
71
44
 
72
- class OpenTransaction < Transaction #:nodoc:
73
- attr_reader :parent, :records
74
- attr_writer :joinable
75
-
76
- def initialize(connection, parent, options = {})
77
- super connection
78
-
79
- @parent = parent
80
- @records = []
81
- @finishing = false
82
- @joinable = options.fetch(:joinable, true)
83
- end
84
-
85
- # This state is necessary so that we correctly handle stuff that might
86
- # happen in a commit/rollback. But it's kinda distasteful. Maybe we can
87
- # find a better way to structure it in the future.
88
- def finishing?
89
- @finishing
90
- end
45
+ class Transaction #:nodoc:
91
46
 
92
- def joinable?
93
- @joinable && !finishing?
94
- end
47
+ attr_reader :connection, :state, :records, :savepoint_name
48
+ attr_writer :joinable
95
49
 
96
- def number
97
- if finishing?
98
- parent.number
99
- else
100
- parent.number + 1
101
- end
50
+ def initialize(connection, options)
51
+ @connection = connection
52
+ @state = TransactionState.new
53
+ @records = []
54
+ @joinable = options.fetch(:joinable, true)
102
55
  end
103
56
 
104
- def begin(options = {})
105
- if finishing?
106
- parent.begin
107
- else
108
- SavepointTransaction.new(connection, self, options)
109
- end
57
+ def add_record(record)
58
+ records << record
110
59
  end
111
60
 
112
61
  def rollback
113
- @finishing = true
114
- perform_rollback
115
- parent
116
- end
117
-
118
- def commit
119
- @finishing = true
120
- perform_commit
121
- parent
122
- end
123
-
124
- def add_record(record)
125
- if record.has_transactional_callbacks?
126
- records << record
127
- else
128
- record.set_transaction_state(@state)
129
- end
62
+ @state.set_state(:rolledback)
130
63
  end
131
64
 
132
65
  def rollback_records
133
- @state.set_state(:rolledback)
134
- records.uniq.each do |record|
66
+ ite = records.uniq
67
+ while record = ite.shift
135
68
  begin
136
- record.rolledback!(parent.closed?)
69
+ record.rolledback! full_rollback?
137
70
  rescue => e
71
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
138
72
  record.logger.error(e) if record.respond_to?(:logger) && record.logger
139
73
  end
140
74
  end
75
+ ensure
76
+ ite.each do |i|
77
+ i.rolledback!(full_rollback?, false)
78
+ end
141
79
  end
142
80
 
143
- def commit_records
81
+ def commit
144
82
  @state.set_state(:committed)
145
- records.uniq.each do |record|
83
+ end
84
+
85
+ def commit_records
86
+ ite = records.uniq
87
+ while record = ite.shift
146
88
  begin
147
89
  record.committed!
148
90
  rescue => e
91
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
149
92
  record.logger.error(e) if record.respond_to?(:logger) && record.logger
150
93
  end
151
94
  end
95
+ ensure
96
+ ite.each do |i|
97
+ i.committed!(false)
98
+ end
152
99
  end
153
100
 
154
- def closed?
155
- false
101
+ def full_rollback?; true; end
102
+ def joinable?; @joinable; end
103
+ def closed?; false; end
104
+ def open?; !closed?; end
105
+ end
106
+
107
+ class SavepointTransaction < Transaction
108
+
109
+ def initialize(connection, savepoint_name, options)
110
+ super(connection, options)
111
+ if options[:isolation]
112
+ raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
113
+ end
114
+ connection.create_savepoint(@savepoint_name = savepoint_name)
156
115
  end
157
116
 
158
- def open?
159
- true
117
+ def rollback
118
+ connection.rollback_to_savepoint(savepoint_name)
119
+ super
120
+ rollback_records
160
121
  end
161
- end
162
122
 
163
- class RealTransaction < OpenTransaction #:nodoc:
164
- def initialize(connection, parent, options = {})
123
+ def commit
124
+ connection.release_savepoint(savepoint_name)
165
125
  super
126
+ parent = connection.transaction_manager.current_transaction
127
+ records.each { |r| parent.add_record(r) }
128
+ end
129
+
130
+ def full_rollback?; false; end
131
+ end
166
132
 
133
+ class RealTransaction < Transaction
134
+
135
+ def initialize(connection, options)
136
+ super
167
137
  if options[:isolation]
168
138
  connection.begin_isolated_db_transaction(options[:isolation])
169
139
  else
@@ -171,38 +141,75 @@ module ActiveRecord
171
141
  end
172
142
  end
173
143
 
174
- def perform_rollback
144
+ def rollback
175
145
  connection.rollback_db_transaction
146
+ super
176
147
  rollback_records
177
148
  end
178
149
 
179
- def perform_commit
150
+ def commit
180
151
  connection.commit_db_transaction
152
+ super
181
153
  commit_records
182
154
  end
183
155
  end
184
156
 
185
- class SavepointTransaction < OpenTransaction #:nodoc:
186
- def initialize(connection, parent, options = {})
187
- if options[:isolation]
188
- raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
189
- end
157
+ class TransactionManager #:nodoc:
158
+ def initialize(connection)
159
+ @stack = []
160
+ @connection = connection
161
+ end
190
162
 
191
- super
192
- connection.create_savepoint
163
+ def begin_transaction(options = {})
164
+ transaction =
165
+ if @stack.empty?
166
+ RealTransaction.new(@connection, options)
167
+ else
168
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options)
169
+ end
170
+ @stack.push(transaction)
171
+ transaction
172
+ end
173
+
174
+ def commit_transaction
175
+ @stack.pop.commit
176
+ end
177
+
178
+ def rollback_transaction
179
+ @stack.pop.rollback
180
+ end
181
+
182
+ def within_new_transaction(options = {})
183
+ transaction = begin_transaction options
184
+ yield
185
+ rescue Exception => error
186
+ rollback_transaction if transaction
187
+ raise
188
+ ensure
189
+ unless error
190
+ if Thread.current.status == 'aborting'
191
+ rollback_transaction if transaction
192
+ else
193
+ begin
194
+ commit_transaction
195
+ rescue Exception
196
+ transaction.rollback unless transaction.state.completed?
197
+ raise
198
+ end
199
+ end
200
+ end
193
201
  end
194
202
 
195
- def perform_rollback
196
- connection.rollback_to_savepoint
197
- rollback_records
203
+ def open_transactions
204
+ @stack.size
198
205
  end
199
206
 
200
- def perform_commit
201
- @state.set_state(:committed)
202
- @state.parent = parent.state
203
- connection.release_savepoint
204
- records.each { |r| parent.add_record(r) }
207
+ def current_transaction
208
+ @stack.last || NULL_TRANSACTION
205
209
  end
210
+
211
+ private
212
+ NULL_TRANSACTION = NullTransaction.new
206
213
  end
207
214
  end
208
215
  end