activerecord 4.1.16 → 4.2.0.beta1

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +634 -2185
  3. data/README.rdoc +15 -10
  4. data/lib/active_record.rb +2 -1
  5. data/lib/active_record/aggregations.rb +12 -8
  6. data/lib/active_record/associations.rb +58 -33
  7. data/lib/active_record/associations/association.rb +1 -1
  8. data/lib/active_record/associations/association_scope.rb +53 -21
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  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/has_and_belongs_to_many.rb +2 -11
  13. data/lib/active_record/associations/builder/has_one.rb +2 -2
  14. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  15. data/lib/active_record/associations/collection_association.rb +32 -44
  16. data/lib/active_record/associations/collection_proxy.rb +1 -10
  17. data/lib/active_record/associations/has_many_association.rb +60 -14
  18. data/lib/active_record/associations/has_many_through_association.rb +34 -23
  19. data/lib/active_record/associations/has_one_association.rb +0 -1
  20. data/lib/active_record/associations/join_dependency.rb +7 -9
  21. data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
  22. data/lib/active_record/associations/preloader.rb +2 -2
  23. data/lib/active_record/associations/preloader/association.rb +9 -5
  24. data/lib/active_record/associations/preloader/through_association.rb +3 -3
  25. data/lib/active_record/associations/singular_association.rb +16 -1
  26. data/lib/active_record/associations/through_association.rb +6 -22
  27. data/lib/active_record/attribute.rb +131 -0
  28. data/lib/active_record/attribute_assignment.rb +19 -11
  29. data/lib/active_record/attribute_decorators.rb +66 -0
  30. data/lib/active_record/attribute_methods.rb +53 -90
  31. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
  32. data/lib/active_record/attribute_methods/dirty.rb +85 -42
  33. data/lib/active_record/attribute_methods/primary_key.rb +6 -8
  34. data/lib/active_record/attribute_methods/read.rb +14 -57
  35. data/lib/active_record/attribute_methods/serialization.rb +12 -146
  36. data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
  37. data/lib/active_record/attribute_methods/write.rb +8 -23
  38. data/lib/active_record/attribute_set.rb +77 -0
  39. data/lib/active_record/attribute_set/builder.rb +32 -0
  40. data/lib/active_record/attributes.rb +122 -0
  41. data/lib/active_record/autosave_association.rb +11 -21
  42. data/lib/active_record/base.rb +9 -19
  43. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
  44. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
  53. data/lib/active_record/connection_adapters/column.rb +13 -244
  54. data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
  55. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
  56. data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
  57. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  58. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  59. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -20
  60. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
  61. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -0
  62. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  64. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  65. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  66. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  67. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  68. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  69. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +76 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +85 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  86. data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
  87. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  88. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
  89. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
  90. data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
  91. data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
  92. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  93. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
  94. data/lib/active_record/connection_handling.rb +1 -1
  95. data/lib/active_record/core.rb +119 -22
  96. data/lib/active_record/counter_cache.rb +60 -6
  97. data/lib/active_record/enum.rb +9 -10
  98. data/lib/active_record/errors.rb +27 -26
  99. data/lib/active_record/explain.rb +1 -1
  100. data/lib/active_record/fixtures.rb +52 -45
  101. data/lib/active_record/gem_version.rb +3 -3
  102. data/lib/active_record/inheritance.rb +33 -8
  103. data/lib/active_record/integration.rb +4 -4
  104. data/lib/active_record/locking/optimistic.rb +34 -16
  105. data/lib/active_record/migration.rb +22 -32
  106. data/lib/active_record/migration/command_recorder.rb +19 -2
  107. data/lib/active_record/migration/join_table.rb +1 -1
  108. data/lib/active_record/model_schema.rb +39 -48
  109. data/lib/active_record/nested_attributes.rb +8 -18
  110. data/lib/active_record/persistence.rb +39 -22
  111. data/lib/active_record/query_cache.rb +3 -3
  112. data/lib/active_record/querying.rb +1 -8
  113. data/lib/active_record/railtie.rb +17 -10
  114. data/lib/active_record/railties/databases.rake +47 -42
  115. data/lib/active_record/readonly_attributes.rb +0 -1
  116. data/lib/active_record/reflection.rb +225 -92
  117. data/lib/active_record/relation.rb +35 -11
  118. data/lib/active_record/relation/batches.rb +0 -2
  119. data/lib/active_record/relation/calculations.rb +28 -32
  120. data/lib/active_record/relation/delegation.rb +1 -1
  121. data/lib/active_record/relation/finder_methods.rb +42 -20
  122. data/lib/active_record/relation/merger.rb +0 -1
  123. data/lib/active_record/relation/predicate_builder.rb +1 -22
  124. data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
  125. data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
  126. data/lib/active_record/relation/query_methods.rb +98 -62
  127. data/lib/active_record/relation/spawn_methods.rb +6 -7
  128. data/lib/active_record/result.rb +16 -9
  129. data/lib/active_record/sanitization.rb +8 -1
  130. data/lib/active_record/schema.rb +0 -1
  131. data/lib/active_record/schema_dumper.rb +51 -9
  132. data/lib/active_record/schema_migration.rb +4 -0
  133. data/lib/active_record/scoping/default.rb +5 -4
  134. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  135. data/lib/active_record/statement_cache.rb +79 -5
  136. data/lib/active_record/store.rb +5 -5
  137. data/lib/active_record/tasks/database_tasks.rb +37 -5
  138. data/lib/active_record/tasks/mysql_database_tasks.rb +10 -16
  139. data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
  140. data/lib/active_record/timestamp.rb +9 -7
  141. data/lib/active_record/transactions.rb +35 -21
  142. data/lib/active_record/type.rb +20 -0
  143. data/lib/active_record/type/binary.rb +40 -0
  144. data/lib/active_record/type/boolean.rb +19 -0
  145. data/lib/active_record/type/date.rb +46 -0
  146. data/lib/active_record/type/date_time.rb +43 -0
  147. data/lib/active_record/type/decimal.rb +40 -0
  148. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  149. data/lib/active_record/type/float.rb +19 -0
  150. data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
  151. data/lib/active_record/type/integer.rb +23 -0
  152. data/lib/active_record/type/mutable.rb +16 -0
  153. data/lib/active_record/type/numeric.rb +36 -0
  154. data/lib/active_record/type/serialized.rb +51 -0
  155. data/lib/active_record/type/string.rb +36 -0
  156. data/lib/active_record/type/text.rb +11 -0
  157. data/lib/active_record/type/time.rb +26 -0
  158. data/lib/active_record/type/time_value.rb +38 -0
  159. data/lib/active_record/type/type_map.rb +48 -0
  160. data/lib/active_record/type/value.rb +101 -0
  161. data/lib/active_record/validations.rb +21 -16
  162. data/lib/active_record/validations/uniqueness.rb +9 -23
  163. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  164. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  165. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  166. metadata +71 -14
  167. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,4 +1,3 @@
1
-
2
1
  module ActiveRecord
3
2
  # = Active Record Timestamp
4
3
  #
@@ -48,8 +47,9 @@ module ActiveRecord
48
47
  current_time = current_time_from_proper_timezone
49
48
 
50
49
  all_timestamp_attributes.each do |column|
51
- if respond_to?(column) && respond_to?("#{column}=") && self.send(column).nil?
52
- write_attribute(column.to_s, current_time)
50
+ column = column.to_s
51
+ if has_attribute?(column) && !attribute_present?(column)
52
+ write_attribute(column, current_time)
53
53
  end
54
54
  end
55
55
  end
@@ -99,9 +99,11 @@ module ActiveRecord
99
99
  end
100
100
 
101
101
  def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update)
102
- if (timestamps = timestamp_names.map { |attr| self[attr] }.compact).present?
103
- timestamps.map { |ts| ts.to_time }.max
104
- end
102
+ timestamp_names
103
+ .map { |attr| self[attr] }
104
+ .compact
105
+ .map(&:to_time)
106
+ .max
105
107
  end
106
108
 
107
109
  def current_time_from_proper_timezone
@@ -112,7 +114,7 @@ module ActiveRecord
112
114
  def clear_timestamp_attributes
113
115
  all_timestamp_attributes_in_model.each do |attribute_name|
114
116
  self[attribute_name] = nil
115
- changed_attributes.delete(attribute_name)
117
+ clear_attribute_changes([attribute_name])
116
118
  end
117
119
  end
118
120
  end
@@ -1,15 +1,25 @@
1
- require 'thread'
2
-
3
1
  module ActiveRecord
4
2
  # See ActiveRecord::Transactions::ClassMethods for documentation.
5
3
  module Transactions
6
4
  extend ActiveSupport::Concern
7
5
  ACTIONS = [:create, :destroy, :update]
6
+ CALLBACK_WARN_MESSAGE = <<-EOF
7
+ Currently, Active Record will rescue any errors raised within
8
+ after_rollback/after_commit callbacks and print them to the logs. In the next
9
+ version, these errors will no longer be rescued. Instead, they will simply
10
+ bubble just like other Active Record callbacks.
11
+
12
+ You can opt into the new behavior and remove this warning by setting
13
+ config.active_record.raise_in_transactional_callbacks to true.
14
+ EOF
8
15
 
9
16
  included do
10
17
  define_callbacks :commit, :rollback,
11
18
  terminator: ->(_, result) { result == false },
12
19
  scope: [:kind, :name]
20
+
21
+ mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
22
+ self.raise_in_transactional_callbacks = false
13
23
  end
14
24
 
15
25
  # = Active Record Transactions
@@ -225,6 +235,9 @@ module ActiveRecord
225
235
  def after_commit(*args, &block)
226
236
  set_options_for_callbacks!(args)
227
237
  set_callback(:commit, :after, *args, &block)
238
+ unless ActiveRecord::Base.raise_in_transactional_callbacks
239
+ ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
240
+ end
228
241
  end
229
242
 
230
243
  # This callback is called after a create, update, or destroy are rolled back.
@@ -233,6 +246,9 @@ module ActiveRecord
233
246
  def after_rollback(*args, &block)
234
247
  set_options_for_callbacks!(args)
235
248
  set_callback(:rollback, :after, *args, &block)
249
+ unless ActiveRecord::Base.raise_in_transactional_callbacks
250
+ ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
251
+ end
236
252
  end
237
253
 
238
254
  private
@@ -249,7 +265,7 @@ module ActiveRecord
249
265
 
250
266
  def assert_valid_transaction_action(actions)
251
267
  if (actions - ACTIONS).any?
252
- raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
268
+ raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS.join(",")}"
253
269
  end
254
270
  end
255
271
  end
@@ -292,16 +308,16 @@ module ActiveRecord
292
308
  #
293
309
  # Ensure that it is not called if the object was never persisted (failed create),
294
310
  # but call it after the commit of a destroyed object.
295
- def committed! #:nodoc:
296
- run_callbacks :commit if destroyed? || persisted?
311
+ def committed!(should_run_callbacks = true) #:nodoc:
312
+ run_callbacks :commit if should_run_callbacks && destroyed? || persisted?
297
313
  ensure
298
- @_start_transaction_state.clear
314
+ force_clear_transaction_record_state
299
315
  end
300
316
 
301
317
  # Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
302
318
  # state should be rolled back to the beginning or just to the last savepoint.
303
- def rolledback!(force_restore_state = false) #:nodoc:
304
- run_callbacks :rollback
319
+ def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
320
+ run_callbacks :rollback if should_run_callbacks
305
321
  ensure
306
322
  restore_transaction_record_state(force_restore_state)
307
323
  clear_transaction_record_state
@@ -328,7 +344,7 @@ module ActiveRecord
328
344
  begin
329
345
  status = yield
330
346
  rescue ActiveRecord::Rollback
331
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
347
+ clear_transaction_record_state
332
348
  status = nil
333
349
  end
334
350
 
@@ -341,7 +357,7 @@ module ActiveRecord
341
357
 
342
358
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
343
359
  def remember_transaction_record_state #:nodoc:
344
- @_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
360
+ @_start_transaction_state[:id] = id
345
361
  unless @_start_transaction_state.include?(:new_record)
346
362
  @_start_transaction_state[:new_record] = @new_record
347
363
  end
@@ -349,13 +365,18 @@ module ActiveRecord
349
365
  @_start_transaction_state[:destroyed] = @destroyed
350
366
  end
351
367
  @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
352
- @_start_transaction_state[:frozen?] = @attributes.frozen?
368
+ @_start_transaction_state[:frozen?] = frozen?
353
369
  end
354
370
 
355
371
  # Clear the new record state and id of a record.
356
372
  def clear_transaction_record_state #:nodoc:
357
373
  @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
358
- @_start_transaction_state.clear if @_start_transaction_state[:level] < 1
374
+ force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
375
+ end
376
+
377
+ # Force to clear the transaction record state.
378
+ def force_clear_transaction_record_state #:nodoc:
379
+ @_start_transaction_state.clear
359
380
  end
360
381
 
361
382
  # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
@@ -364,17 +385,10 @@ module ActiveRecord
364
385
  transaction_level = (@_start_transaction_state[:level] || 0) - 1
365
386
  if transaction_level < 1 || force
366
387
  restore_state = @_start_transaction_state
367
- was_frozen = restore_state[:frozen?]
368
- @attributes = @attributes.dup if @attributes.frozen?
388
+ thaw unless restore_state[:frozen?]
369
389
  @new_record = restore_state[:new_record]
370
390
  @destroyed = restore_state[:destroyed]
371
- if restore_state.has_key?(:id)
372
- write_attribute(self.class.primary_key, restore_state[:id])
373
- else
374
- @attributes.delete(self.class.primary_key)
375
- @attributes_cache.delete(self.class.primary_key)
376
- end
377
- @attributes.freeze if was_frozen
391
+ write_attribute(self.class.primary_key, restore_state[:id])
378
392
  end
379
393
  end
380
394
  end
@@ -0,0 +1,20 @@
1
+ require 'active_record/type/mutable'
2
+ require 'active_record/type/numeric'
3
+ require 'active_record/type/time_value'
4
+ require 'active_record/type/value'
5
+
6
+ require 'active_record/type/binary'
7
+ require 'active_record/type/boolean'
8
+ require 'active_record/type/date'
9
+ require 'active_record/type/date_time'
10
+ require 'active_record/type/decimal'
11
+ require 'active_record/type/decimal_without_scale'
12
+ require 'active_record/type/float'
13
+ require 'active_record/type/integer'
14
+ require 'active_record/type/serialized'
15
+ require 'active_record/type/string'
16
+ require 'active_record/type/text'
17
+ require 'active_record/type/time'
18
+
19
+ require 'active_record/type/type_map'
20
+ require 'active_record/type/hash_lookup_type_map'
@@ -0,0 +1,40 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Binary < Value # :nodoc:
4
+ def type
5
+ :binary
6
+ end
7
+
8
+ def binary?
9
+ true
10
+ end
11
+
12
+ def type_cast(value)
13
+ if value.is_a?(Data)
14
+ value.to_s
15
+ else
16
+ super
17
+ end
18
+ end
19
+
20
+ def type_cast_for_database(value)
21
+ return if value.nil?
22
+ Data.new(super)
23
+ end
24
+
25
+ class Data # :nodoc:
26
+ def initialize(value)
27
+ @value = value.to_s
28
+ end
29
+
30
+ def to_s
31
+ @value
32
+ end
33
+
34
+ def hex
35
+ @value.unpack('H*')[0]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Boolean < Value # :nodoc:
4
+ def type
5
+ :boolean
6
+ end
7
+
8
+ private
9
+
10
+ def cast_value(value)
11
+ if value == ''
12
+ nil
13
+ else
14
+ ConnectionAdapters::Column::TRUE_VALUES.include?(value)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Date < Value # :nodoc:
4
+ def type
5
+ :date
6
+ end
7
+
8
+ def klass
9
+ ::Date
10
+ end
11
+
12
+ def type_cast_for_schema(value)
13
+ "'#{value.to_s(:db)}'"
14
+ end
15
+
16
+ private
17
+
18
+ def cast_value(value)
19
+ if value.is_a?(::String)
20
+ return if value.empty?
21
+ fast_string_to_date(value) || fallback_string_to_date(value)
22
+ elsif value.respond_to?(:to_date)
23
+ value.to_date
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ def fast_string_to_date(string)
30
+ if string =~ ConnectionAdapters::Column::Format::ISO_DATE
31
+ new_date $1.to_i, $2.to_i, $3.to_i
32
+ end
33
+ end
34
+
35
+ def fallback_string_to_date(string)
36
+ new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
37
+ end
38
+
39
+ def new_date(year, mon, mday)
40
+ if year && year != 0
41
+ ::Date.new(year, mon, mday) rescue nil
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class DateTime < Value # :nodoc:
4
+ include TimeValue
5
+
6
+ def type
7
+ :datetime
8
+ end
9
+
10
+ def type_cast_for_database(value)
11
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
12
+
13
+ if value.acts_like?(:time)
14
+ value.send(zone_conversion_method)
15
+ else
16
+ super
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def cast_value(string)
23
+ return string unless string.is_a?(::String)
24
+ return if string.empty?
25
+
26
+ fast_string_to_time(string) || fallback_string_to_time(string)
27
+ end
28
+
29
+ # '0.123456' -> 123456
30
+ # '1.123456' -> 123456
31
+ def microseconds(time)
32
+ time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
33
+ end
34
+
35
+ def fallback_string_to_time(string)
36
+ time_hash = ::Date._parse(string)
37
+ time_hash[:sec_fraction] = microseconds(time_hash)
38
+
39
+ new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,40 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Decimal < Value # :nodoc:
4
+ include Numeric
5
+
6
+ def type
7
+ :decimal
8
+ end
9
+
10
+ def type_cast_for_schema(value)
11
+ value.to_s
12
+ end
13
+
14
+ private
15
+
16
+ def cast_value(value)
17
+ case value
18
+ when ::Float
19
+ BigDecimal(value, float_precision)
20
+ when ::Numeric, ::String
21
+ BigDecimal(value, precision.to_i)
22
+ else
23
+ if value.respond_to?(:to_d)
24
+ value.to_d
25
+ else
26
+ cast_value(value.to_s)
27
+ end
28
+ end
29
+ end
30
+
31
+ def float_precision
32
+ if precision.to_i > ::Float::DIG + 1
33
+ ::Float::DIG + 1
34
+ else
35
+ precision.to_i
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ require 'active_record/type/integer'
2
+
3
+ module ActiveRecord
4
+ module Type
5
+ class DecimalWithoutScale < Integer # :nodoc:
6
+ def type
7
+ :decimal
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Float < Value # :nodoc:
4
+ include Numeric
5
+
6
+ def type
7
+ :float
8
+ end
9
+
10
+ alias type_cast_for_database type_cast
11
+
12
+ private
13
+
14
+ def cast_value(value)
15
+ value.to_f
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class HashLookupTypeMap < TypeMap # :nodoc:
4
+ delegate :key?, to: :@mapping
5
+
6
+ def lookup(type, *args)
7
+ @mapping.fetch(type, proc { default_value }).call(type, *args)
8
+ end
9
+
10
+ def fetch(type, *args, &block)
11
+ @mapping.fetch(type, block).call(type, *args)
12
+ end
13
+
14
+ def alias_type(type, alias_type)
15
+ register_type(type) { |_, *args| lookup(alias_type, *args) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Integer < Value # :nodoc:
4
+ include Numeric
5
+
6
+ def type
7
+ :integer
8
+ end
9
+
10
+ alias type_cast_for_database type_cast
11
+
12
+ private
13
+
14
+ def cast_value(value)
15
+ case value
16
+ when true then 1
17
+ when false then 0
18
+ else value.to_i rescue nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end