activerecord 4.1.15 → 4.2.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (185) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1162 -1792
  3. data/README.rdoc +15 -10
  4. data/lib/active_record.rb +4 -0
  5. data/lib/active_record/aggregations.rb +15 -8
  6. data/lib/active_record/association_relation.rb +13 -0
  7. data/lib/active_record/associations.rb +158 -49
  8. data/lib/active_record/associations/alias_tracker.rb +3 -12
  9. data/lib/active_record/associations/association.rb +16 -4
  10. data/lib/active_record/associations/association_scope.rb +83 -38
  11. data/lib/active_record/associations/belongs_to_association.rb +28 -10
  12. data/lib/active_record/associations/builder/association.rb +15 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -13
  16. data/lib/active_record/associations/builder/has_many.rb +1 -1
  17. data/lib/active_record/associations/builder/has_one.rb +2 -2
  18. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  19. data/lib/active_record/associations/collection_association.rb +63 -27
  20. data/lib/active_record/associations/collection_proxy.rb +29 -35
  21. data/lib/active_record/associations/foreign_association.rb +11 -0
  22. data/lib/active_record/associations/has_many_association.rb +83 -22
  23. data/lib/active_record/associations/has_many_through_association.rb +49 -26
  24. data/lib/active_record/associations/has_one_association.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +26 -13
  26. data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
  27. data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
  28. data/lib/active_record/associations/preloader.rb +36 -26
  29. data/lib/active_record/associations/preloader/association.rb +14 -11
  30. data/lib/active_record/associations/preloader/through_association.rb +4 -3
  31. data/lib/active_record/associations/singular_association.rb +17 -2
  32. data/lib/active_record/associations/through_association.rb +5 -12
  33. data/lib/active_record/attribute.rb +163 -0
  34. data/lib/active_record/attribute_assignment.rb +19 -11
  35. data/lib/active_record/attribute_decorators.rb +66 -0
  36. data/lib/active_record/attribute_methods.rb +56 -94
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  38. data/lib/active_record/attribute_methods/dirty.rb +107 -43
  39. data/lib/active_record/attribute_methods/primary_key.rb +7 -8
  40. data/lib/active_record/attribute_methods/query.rb +1 -1
  41. data/lib/active_record/attribute_methods/read.rb +22 -59
  42. data/lib/active_record/attribute_methods/serialization.rb +16 -150
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -40
  44. data/lib/active_record/attribute_methods/write.rb +9 -24
  45. data/lib/active_record/attribute_set.rb +81 -0
  46. data/lib/active_record/attribute_set/builder.rb +106 -0
  47. data/lib/active_record/attributes.rb +147 -0
  48. data/lib/active_record/autosave_association.rb +19 -12
  49. data/lib/active_record/base.rb +13 -24
  50. data/lib/active_record/callbacks.rb +6 -6
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +84 -52
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
  55. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  56. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
  57. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +138 -56
  58. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +268 -71
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +171 -59
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +293 -139
  63. data/lib/active_record/connection_adapters/column.rb +29 -240
  64. data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +67 -144
  67. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  68. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
  70. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
  71. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  99. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +131 -43
  100. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  101. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
  102. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  103. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
  104. data/lib/active_record/connection_handling.rb +1 -1
  105. data/lib/active_record/core.rb +163 -39
  106. data/lib/active_record/counter_cache.rb +60 -6
  107. data/lib/active_record/enum.rb +9 -11
  108. data/lib/active_record/errors.rb +53 -30
  109. data/lib/active_record/explain.rb +1 -1
  110. data/lib/active_record/explain_subscriber.rb +1 -1
  111. data/lib/active_record/fixtures.rb +55 -69
  112. data/lib/active_record/gem_version.rb +4 -4
  113. data/lib/active_record/inheritance.rb +35 -10
  114. data/lib/active_record/integration.rb +4 -4
  115. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  116. data/lib/active_record/locking/optimistic.rb +46 -26
  117. data/lib/active_record/migration.rb +71 -46
  118. data/lib/active_record/migration/command_recorder.rb +19 -2
  119. data/lib/active_record/migration/join_table.rb +1 -1
  120. data/lib/active_record/model_schema.rb +52 -58
  121. data/lib/active_record/nested_attributes.rb +5 -5
  122. data/lib/active_record/no_touching.rb +1 -1
  123. data/lib/active_record/persistence.rb +46 -26
  124. data/lib/active_record/query_cache.rb +3 -3
  125. data/lib/active_record/querying.rb +10 -7
  126. data/lib/active_record/railtie.rb +18 -11
  127. data/lib/active_record/railties/databases.rake +50 -51
  128. data/lib/active_record/readonly_attributes.rb +0 -1
  129. data/lib/active_record/reflection.rb +273 -114
  130. data/lib/active_record/relation.rb +57 -25
  131. data/lib/active_record/relation/batches.rb +0 -2
  132. data/lib/active_record/relation/calculations.rb +41 -37
  133. data/lib/active_record/relation/finder_methods.rb +70 -47
  134. data/lib/active_record/relation/merger.rb +39 -29
  135. data/lib/active_record/relation/predicate_builder.rb +16 -8
  136. data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
  137. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -5
  138. data/lib/active_record/relation/query_methods.rb +114 -65
  139. data/lib/active_record/relation/spawn_methods.rb +3 -0
  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 -6
  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 +53 -27
  155. data/lib/active_record/type.rb +23 -0
  156. data/lib/active_record/type/big_integer.rb +13 -0
  157. data/lib/active_record/type/binary.rb +50 -0
  158. data/lib/active_record/type/boolean.rb +31 -0
  159. data/lib/active_record/type/date.rb +50 -0
  160. data/lib/active_record/type/date_time.rb +54 -0
  161. data/lib/active_record/type/decimal.rb +64 -0
  162. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  163. data/lib/active_record/type/decorator.rb +14 -0
  164. data/lib/active_record/type/float.rb +19 -0
  165. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  166. data/lib/active_record/type/integer.rb +59 -0
  167. data/lib/active_record/type/mutable.rb +16 -0
  168. data/lib/active_record/type/numeric.rb +36 -0
  169. data/lib/active_record/type/serialized.rb +62 -0
  170. data/lib/active_record/type/string.rb +40 -0
  171. data/lib/active_record/type/text.rb +11 -0
  172. data/lib/active_record/type/time.rb +26 -0
  173. data/lib/active_record/type/time_value.rb +38 -0
  174. data/lib/active_record/type/type_map.rb +64 -0
  175. data/lib/active_record/type/unsigned_integer.rb +15 -0
  176. data/lib/active_record/type/value.rb +110 -0
  177. data/lib/active_record/validations.rb +25 -19
  178. data/lib/active_record/validations/associated.rb +5 -3
  179. data/lib/active_record/validations/presence.rb +5 -3
  180. data/lib/active_record/validations/uniqueness.rb +25 -29
  181. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  182. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  183. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  184. metadata +66 -11
  185. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -0,0 +1,23 @@
1
+ require 'active_record/type/decorator'
2
+ require 'active_record/type/mutable'
3
+ require 'active_record/type/numeric'
4
+ require 'active_record/type/time_value'
5
+ require 'active_record/type/value'
6
+
7
+ require 'active_record/type/big_integer'
8
+ require 'active_record/type/binary'
9
+ require 'active_record/type/boolean'
10
+ require 'active_record/type/date'
11
+ require 'active_record/type/date_time'
12
+ require 'active_record/type/decimal'
13
+ require 'active_record/type/decimal_without_scale'
14
+ require 'active_record/type/float'
15
+ require 'active_record/type/integer'
16
+ require 'active_record/type/serialized'
17
+ require 'active_record/type/string'
18
+ require 'active_record/type/text'
19
+ require 'active_record/type/time'
20
+ require 'active_record/type/unsigned_integer'
21
+
22
+ require 'active_record/type/type_map'
23
+ require 'active_record/type/hash_lookup_type_map'
@@ -0,0 +1,13 @@
1
+ require 'active_record/type/integer'
2
+
3
+ module ActiveRecord
4
+ module Type
5
+ class BigInteger < Integer # :nodoc:
6
+ private
7
+
8
+ def max_value
9
+ ::Float::INFINITY
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
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
+ def changed_in_place?(raw_old_value, value)
26
+ old_value = type_cast_from_database(raw_old_value)
27
+ old_value != value
28
+ end
29
+
30
+ class Data # :nodoc:
31
+ def initialize(value)
32
+ @value = value.to_s
33
+ end
34
+
35
+ def to_s
36
+ @value
37
+ end
38
+ alias_method :to_str, :to_s
39
+
40
+ def hex
41
+ @value.unpack('H*')[0]
42
+ end
43
+
44
+ def ==(other)
45
+ other == to_s || super
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,31 @@
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
+ elsif ConnectionAdapters::Column::TRUE_VALUES.include?(value)
14
+ true
15
+ else
16
+ if !ConnectionAdapters::Column::FALSE_VALUES.include?(value)
17
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
18
+ You attempted to assign a value which is not explicitly `true` or `false`
19
+ (#{value.inspect})
20
+ to a boolean column. Currently this value casts to `false`. This will
21
+ change to match Ruby's semantics, and will cast to `true` in Rails 5.
22
+ If you would like to maintain the current behavior, you should
23
+ explicitly handle the values you would like cast to `false`.
24
+ MSG
25
+ end
26
+ false
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
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_database(value)
13
+ type_cast(value)
14
+ end
15
+
16
+ def type_cast_for_schema(value)
17
+ "'#{value.to_s(:db)}'"
18
+ end
19
+
20
+ private
21
+
22
+ def cast_value(value)
23
+ if value.is_a?(::String)
24
+ return if value.empty?
25
+ fast_string_to_date(value) || fallback_string_to_date(value)
26
+ elsif value.respond_to?(:to_date)
27
+ value.to_date
28
+ else
29
+ value
30
+ end
31
+ end
32
+
33
+ def fast_string_to_date(string)
34
+ if string =~ ConnectionAdapters::Column::Format::ISO_DATE
35
+ new_date $1.to_i, $2.to_i, $3.to_i
36
+ end
37
+ end
38
+
39
+ def fallback_string_to_date(string)
40
+ new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
41
+ end
42
+
43
+ def new_date(year, mon, mday)
44
+ if year && year != 0
45
+ ::Date.new(year, mon, mday) rescue nil
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
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
+ return super unless value.acts_like?(:time)
12
+
13
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
14
+
15
+ if value.respond_to?(zone_conversion_method)
16
+ value = value.send(zone_conversion_method)
17
+ end
18
+
19
+ return value unless has_precision?
20
+
21
+ result = value.to_s(:db)
22
+ if value.respond_to?(:usec) && (1..6).cover?(precision)
23
+ "#{result}.#{sprintf("%0#{precision}d", value.usec / 10 ** (6 - precision))}"
24
+ else
25
+ result
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ alias has_precision? precision
32
+
33
+ def cast_value(string)
34
+ return string unless string.is_a?(::String)
35
+ return if string.empty?
36
+
37
+ fast_string_to_time(string) || fallback_string_to_time(string)
38
+ end
39
+
40
+ # '0.123456' -> 123456
41
+ # '1.123456' -> 123456
42
+ def microseconds(time)
43
+ time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
44
+ end
45
+
46
+ def fallback_string_to_time(string)
47
+ time_hash = ::Date._parse(string)
48
+ time_hash[:sec_fraction] = microseconds(time_hash)
49
+
50
+ new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,64 @@
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
+ casted_value = case value
18
+ when ::Float
19
+ convert_float_to_big_decimal(value)
20
+ when ::Numeric
21
+ BigDecimal(value, precision.to_i)
22
+ when ::String
23
+ begin
24
+ value.to_d
25
+ rescue ArgumentError
26
+ BigDecimal(0)
27
+ end
28
+ else
29
+ if value.respond_to?(:to_d)
30
+ value.to_d
31
+ else
32
+ cast_value(value.to_s)
33
+ end
34
+ end
35
+
36
+ apply_scale(casted_value)
37
+ end
38
+
39
+ def convert_float_to_big_decimal(value)
40
+ if precision
41
+ BigDecimal(apply_scale(value), float_precision)
42
+ else
43
+ value.to_d
44
+ end
45
+ end
46
+
47
+ def float_precision
48
+ if precision.to_i > ::Float::DIG + 1
49
+ ::Float::DIG + 1
50
+ else
51
+ precision.to_i
52
+ end
53
+ end
54
+
55
+ def apply_scale(value)
56
+ if scale
57
+ value.round(scale)
58
+ else
59
+ value
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,11 @@
1
+ require 'active_record/type/big_integer'
2
+
3
+ module ActiveRecord
4
+ module Type
5
+ class DecimalWithoutScale < BigInteger # :nodoc:
6
+ def type
7
+ :decimal
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ module Type
3
+ module Decorator # :nodoc:
4
+ def init_with(coder)
5
+ @subtype = coder['subtype']
6
+ __setobj__(@subtype)
7
+ end
8
+
9
+ def encode_with(coder)
10
+ coder['subtype'] = __getobj__
11
+ end
12
+ end
13
+ end
14
+ 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,23 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class HashLookupTypeMap < TypeMap # :nodoc:
4
+ def alias_type(type, alias_type)
5
+ register_type(type) { |_, *args| lookup(alias_type, *args) }
6
+ end
7
+
8
+ def key?(key)
9
+ @mapping.key?(key)
10
+ end
11
+
12
+ def keys
13
+ @mapping.keys
14
+ end
15
+
16
+ private
17
+
18
+ def perform_fetch(type, *args, &block)
19
+ @mapping.fetch(type, block).call(type, *args)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class Integer < Value # :nodoc:
4
+ include Numeric
5
+
6
+ def initialize(*)
7
+ super
8
+ @range = min_value...max_value
9
+ end
10
+
11
+ def type
12
+ :integer
13
+ end
14
+
15
+ def type_cast_from_database(value)
16
+ return if value.nil?
17
+ value.to_i
18
+ end
19
+
20
+ def type_cast_for_database(value)
21
+ result = type_cast(value)
22
+ if result
23
+ ensure_in_range(result)
24
+ end
25
+ result
26
+ end
27
+
28
+ protected
29
+
30
+ attr_reader :range
31
+
32
+ private
33
+
34
+ def cast_value(value)
35
+ case value
36
+ when true then 1
37
+ when false then 0
38
+ else
39
+ value.to_i rescue nil
40
+ end
41
+ end
42
+
43
+ def ensure_in_range(value)
44
+ unless range.cover?(value)
45
+ raise RangeError, "#{value} is out of range for #{self.class} with limit #{limit || 4}"
46
+ end
47
+ end
48
+
49
+ def max_value
50
+ limit = self.limit || 4
51
+ 1 << (limit * 8 - 1) # 8 bits per byte with one bit for sign
52
+ end
53
+
54
+ def min_value
55
+ -max_value
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveRecord
2
+ module Type
3
+ module Mutable # :nodoc:
4
+ def type_cast_from_user(value)
5
+ type_cast_from_database(type_cast_for_database(value))
6
+ end
7
+
8
+ # +raw_old_value+ will be the `_before_type_cast` version of the
9
+ # value (likely a string). +new_value+ will be the current, type
10
+ # cast value.
11
+ def changed_in_place?(raw_old_value, new_value)
12
+ raw_old_value != type_cast_for_database(new_value)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ module ActiveRecord
2
+ module Type
3
+ module Numeric # :nodoc:
4
+ def number?
5
+ true
6
+ end
7
+
8
+ def type_cast(value)
9
+ value = case value
10
+ when true then 1
11
+ when false then 0
12
+ when ::String then value.presence
13
+ else value
14
+ end
15
+ super(value)
16
+ end
17
+
18
+ def changed?(old_value, _new_value, new_value_before_type_cast) # :nodoc:
19
+ super || number_to_non_number?(old_value, new_value_before_type_cast)
20
+ end
21
+
22
+ private
23
+
24
+ def number_to_non_number?(old_value, new_value_before_type_cast)
25
+ old_value != nil && non_numeric_string?(new_value_before_type_cast)
26
+ end
27
+
28
+ def non_numeric_string?(value)
29
+ # 'wibble'.to_i will give zero, we want to make sure
30
+ # that we aren't marking int zero to string zero as
31
+ # changed.
32
+ value.to_s !~ /\A-?\d+\.?\d*\z/
33
+ end
34
+ end
35
+ end
36
+ end