activerecord 4.2.11.3 → 5.0.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 (229) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1029 -1349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -7
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record.rb +7 -3
  7. data/lib/active_record/aggregations.rb +35 -25
  8. data/lib/active_record/association_relation.rb +2 -2
  9. data/lib/active_record/associations.rb +305 -204
  10. data/lib/active_record/associations/alias_tracker.rb +19 -16
  11. data/lib/active_record/associations/association.rb +10 -8
  12. data/lib/active_record/associations/association_scope.rb +73 -102
  13. data/lib/active_record/associations/belongs_to_association.rb +20 -32
  14. data/lib/active_record/associations/builder/association.rb +28 -34
  15. data/lib/active_record/associations/builder/belongs_to.rb +41 -18
  16. data/lib/active_record/associations/builder/collection_association.rb +8 -24
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
  18. data/lib/active_record/associations/builder/has_many.rb +4 -4
  19. data/lib/active_record/associations/builder/has_one.rb +10 -5
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -9
  21. data/lib/active_record/associations/collection_association.rb +40 -43
  22. data/lib/active_record/associations/collection_proxy.rb +55 -29
  23. data/lib/active_record/associations/foreign_association.rb +1 -1
  24. data/lib/active_record/associations/has_many_association.rb +20 -71
  25. data/lib/active_record/associations/has_many_through_association.rb +8 -52
  26. data/lib/active_record/associations/has_one_association.rb +12 -5
  27. data/lib/active_record/associations/join_dependency.rb +28 -18
  28. data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
  29. data/lib/active_record/associations/preloader.rb +13 -4
  30. data/lib/active_record/associations/preloader/association.rb +45 -51
  31. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +5 -4
  35. data/lib/active_record/associations/singular_association.rb +6 -0
  36. data/lib/active_record/associations/through_association.rb +11 -3
  37. data/lib/active_record/attribute.rb +61 -17
  38. data/lib/active_record/attribute/user_provided_default.rb +23 -0
  39. data/lib/active_record/attribute_assignment.rb +27 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods.rb +79 -26
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  43. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  44. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  45. data/lib/active_record/attribute_methods/query.rb +2 -2
  46. data/lib/active_record/attribute_methods/read.rb +26 -42
  47. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
  49. data/lib/active_record/attribute_methods/write.rb +13 -24
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set.rb +30 -3
  52. data/lib/active_record/attribute_set/builder.rb +6 -4
  53. data/lib/active_record/attributes.rb +194 -81
  54. data/lib/active_record/autosave_association.rb +33 -15
  55. data/lib/active_record/base.rb +30 -18
  56. data/lib/active_record/callbacks.rb +36 -40
  57. data/lib/active_record/coders/yaml_column.rb +20 -8
  58. data/lib/active_record/collection_cache_key.rb +31 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
  70. data/lib/active_record/connection_adapters/column.rb +27 -41
  71. data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
  79. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  85. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  87. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
  92. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
  101. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
  103. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  104. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
  107. data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
  108. data/lib/active_record/connection_handling.rb +5 -5
  109. data/lib/active_record/core.rb +72 -104
  110. data/lib/active_record/counter_cache.rb +9 -20
  111. data/lib/active_record/dynamic_matchers.rb +1 -20
  112. data/lib/active_record/enum.rb +110 -76
  113. data/lib/active_record/errors.rb +72 -47
  114. data/lib/active_record/explain_registry.rb +1 -1
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +19 -4
  117. data/lib/active_record/fixtures.rb +76 -40
  118. data/lib/active_record/gem_version.rb +4 -4
  119. data/lib/active_record/inheritance.rb +27 -40
  120. data/lib/active_record/integration.rb +4 -4
  121. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  122. data/lib/active_record/locale/en.yml +3 -2
  123. data/lib/active_record/locking/optimistic.rb +10 -14
  124. data/lib/active_record/locking/pessimistic.rb +1 -1
  125. data/lib/active_record/log_subscriber.rb +40 -22
  126. data/lib/active_record/migration.rb +304 -133
  127. data/lib/active_record/migration/command_recorder.rb +59 -18
  128. data/lib/active_record/migration/compatibility.rb +90 -0
  129. data/lib/active_record/model_schema.rb +92 -40
  130. data/lib/active_record/nested_attributes.rb +45 -34
  131. data/lib/active_record/null_relation.rb +15 -7
  132. data/lib/active_record/persistence.rb +112 -72
  133. data/lib/active_record/querying.rb +6 -5
  134. data/lib/active_record/railtie.rb +20 -13
  135. data/lib/active_record/railties/controller_runtime.rb +1 -1
  136. data/lib/active_record/railties/databases.rake +47 -38
  137. data/lib/active_record/readonly_attributes.rb +1 -1
  138. data/lib/active_record/reflection.rb +182 -57
  139. data/lib/active_record/relation.rb +152 -100
  140. data/lib/active_record/relation/batches.rb +133 -33
  141. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  142. data/lib/active_record/relation/calculations.rb +80 -101
  143. data/lib/active_record/relation/delegation.rb +6 -19
  144. data/lib/active_record/relation/finder_methods.rb +58 -46
  145. data/lib/active_record/relation/from_clause.rb +32 -0
  146. data/lib/active_record/relation/merger.rb +13 -42
  147. data/lib/active_record/relation/predicate_builder.rb +99 -105
  148. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  149. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
  150. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  151. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  152. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  153. data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
  154. data/lib/active_record/relation/query_attribute.rb +19 -0
  155. data/lib/active_record/relation/query_methods.rb +274 -238
  156. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  157. data/lib/active_record/relation/spawn_methods.rb +3 -6
  158. data/lib/active_record/relation/where_clause.rb +173 -0
  159. data/lib/active_record/relation/where_clause_factory.rb +37 -0
  160. data/lib/active_record/result.rb +4 -3
  161. data/lib/active_record/runtime_registry.rb +1 -1
  162. data/lib/active_record/sanitization.rb +94 -65
  163. data/lib/active_record/schema.rb +23 -22
  164. data/lib/active_record/schema_dumper.rb +33 -22
  165. data/lib/active_record/schema_migration.rb +10 -4
  166. data/lib/active_record/scoping.rb +17 -6
  167. data/lib/active_record/scoping/default.rb +19 -6
  168. data/lib/active_record/scoping/named.rb +39 -28
  169. data/lib/active_record/secure_token.rb +38 -0
  170. data/lib/active_record/serialization.rb +2 -4
  171. data/lib/active_record/statement_cache.rb +15 -13
  172. data/lib/active_record/store.rb +8 -3
  173. data/lib/active_record/suppressor.rb +54 -0
  174. data/lib/active_record/table_metadata.rb +64 -0
  175. data/lib/active_record/tasks/database_tasks.rb +30 -40
  176. data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
  177. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  178. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  179. data/lib/active_record/timestamp.rb +16 -9
  180. data/lib/active_record/touch_later.rb +58 -0
  181. data/lib/active_record/transactions.rb +138 -56
  182. data/lib/active_record/type.rb +66 -17
  183. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  184. data/lib/active_record/type/date.rb +2 -45
  185. data/lib/active_record/type/date_time.rb +2 -49
  186. data/lib/active_record/type/internal/abstract_json.rb +33 -0
  187. data/lib/active_record/type/internal/timezone.rb +15 -0
  188. data/lib/active_record/type/serialized.rb +9 -14
  189. data/lib/active_record/type/time.rb +3 -21
  190. data/lib/active_record/type/type_map.rb +4 -4
  191. data/lib/active_record/type_caster.rb +7 -0
  192. data/lib/active_record/type_caster/connection.rb +29 -0
  193. data/lib/active_record/type_caster/map.rb +19 -0
  194. data/lib/active_record/validations.rb +33 -32
  195. data/lib/active_record/validations/absence.rb +24 -0
  196. data/lib/active_record/validations/associated.rb +10 -3
  197. data/lib/active_record/validations/length.rb +36 -0
  198. data/lib/active_record/validations/presence.rb +12 -12
  199. data/lib/active_record/validations/uniqueness.rb +24 -21
  200. data/lib/rails/generators/active_record/migration.rb +7 -0
  201. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  202. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  203. data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
  204. data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
  205. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  206. metadata +50 -35
  207. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  208. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  209. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  210. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  211. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  212. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  213. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  214. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  215. data/lib/active_record/type/big_integer.rb +0 -13
  216. data/lib/active_record/type/binary.rb +0 -50
  217. data/lib/active_record/type/boolean.rb +0 -31
  218. data/lib/active_record/type/decimal.rb +0 -64
  219. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  220. data/lib/active_record/type/decorator.rb +0 -14
  221. data/lib/active_record/type/float.rb +0 -19
  222. data/lib/active_record/type/integer.rb +0 -59
  223. data/lib/active_record/type/mutable.rb +0 -16
  224. data/lib/active_record/type/numeric.rb +0 -36
  225. data/lib/active_record/type/string.rb +0 -40
  226. data/lib/active_record/type/text.rb +0 -11
  227. data/lib/active_record/type/time_value.rb +0 -38
  228. data/lib/active_record/type/unsigned_integer.rb +0 -15
  229. data/lib/active_record/type/value.rb +0 -110
@@ -2,18 +2,14 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  # PostgreSQL-specific extensions to column definitions in a table.
4
4
  class PostgreSQLColumn < Column #:nodoc:
5
- attr_accessor :array
5
+ delegate :array, :oid, :fmod, to: :sql_type_metadata
6
+ alias :array? :array
6
7
 
7
- def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil)
8
- if sql_type =~ /\[\]$/
9
- @array = true
10
- super(name, default, cast_type, sql_type[0..sql_type.length - 3], null)
11
- else
12
- @array = false
13
- super(name, default, cast_type, sql_type, null)
14
- end
8
+ def serial?
9
+ return unless default_function
15
10
 
16
- @default_function = default_function
11
+ table_name = @table_name || '(?<table_name>.+)'
12
+ %r{\Anextval\('"?#{table_name}_#{name}_seq"?'::regclass\)\z} === default_function
17
13
  end
18
14
  end
19
15
  end
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  end
9
9
 
10
10
  class ExplainPrettyPrinter # :nodoc:
11
- # Pretty prints the result of a EXPLAIN in a way that resembles the output of the
11
+ # Pretty prints the result of an EXPLAIN in a way that resembles the output of the
12
12
  # PostgreSQL shell:
13
13
  #
14
14
  # QUERY PLAN
@@ -156,8 +156,8 @@ module ActiveRecord
156
156
  end
157
157
  end
158
158
 
159
- def exec_query(sql, name = 'SQL', binds = [])
160
- execute_and_clear(sql, name, binds) do |result|
159
+ def exec_query(sql, name = 'SQL', binds = [], prepare: false)
160
+ execute_and_clear(sql, name, binds, prepare: prepare) do |result|
161
161
  types = {}
162
162
  fields = result.fields
163
163
  fields.each_with_index do |fname, i|
@@ -1,25 +1,20 @@
1
- require 'active_record/connection_adapters/postgresql/oid/infinity'
2
-
3
1
  require 'active_record/connection_adapters/postgresql/oid/array'
4
2
  require 'active_record/connection_adapters/postgresql/oid/bit'
5
3
  require 'active_record/connection_adapters/postgresql/oid/bit_varying'
6
4
  require 'active_record/connection_adapters/postgresql/oid/bytea'
7
5
  require 'active_record/connection_adapters/postgresql/oid/cidr'
8
- require 'active_record/connection_adapters/postgresql/oid/date'
9
6
  require 'active_record/connection_adapters/postgresql/oid/date_time'
10
7
  require 'active_record/connection_adapters/postgresql/oid/decimal'
11
8
  require 'active_record/connection_adapters/postgresql/oid/enum'
12
- require 'active_record/connection_adapters/postgresql/oid/float'
13
9
  require 'active_record/connection_adapters/postgresql/oid/hstore'
14
10
  require 'active_record/connection_adapters/postgresql/oid/inet'
15
- require 'active_record/connection_adapters/postgresql/oid/integer'
16
11
  require 'active_record/connection_adapters/postgresql/oid/json'
17
12
  require 'active_record/connection_adapters/postgresql/oid/jsonb'
18
13
  require 'active_record/connection_adapters/postgresql/oid/money'
19
14
  require 'active_record/connection_adapters/postgresql/oid/point'
15
+ require 'active_record/connection_adapters/postgresql/oid/rails_5_1_point'
20
16
  require 'active_record/connection_adapters/postgresql/oid/range'
21
17
  require 'active_record/connection_adapters/postgresql/oid/specialized_string'
22
- require 'active_record/connection_adapters/postgresql/oid/time'
23
18
  require 'active_record/connection_adapters/postgresql/oid/uuid'
24
19
  require 'active_record/connection_adapters/postgresql/oid/vector'
25
20
  require 'active_record/connection_adapters/postgresql/oid/xml'
@@ -3,51 +3,53 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Array < Type::Value # :nodoc:
6
- include Type::Mutable
7
-
8
- # Loads pg_array_parser if available. String parsing can be
9
- # performed quicker by a native extension, which will not create
10
- # a large amount of Ruby objects that will need to be garbage
11
- # collected. pg_array_parser has a C and Java extension
12
- begin
13
- require 'pg_array_parser'
14
- include PgArrayParser
15
- rescue LoadError
16
- require 'active_record/connection_adapters/postgresql/array_parser'
17
- include PostgreSQL::ArrayParser
18
- end
6
+ include Type::Helpers::Mutable
19
7
 
20
8
  attr_reader :subtype, :delimiter
21
- delegate :type, :limit, to: :subtype
9
+ delegate :type, :user_input_in_time_zone, :limit, to: :subtype
22
10
 
23
11
  def initialize(subtype, delimiter = ',')
24
12
  @subtype = subtype
25
13
  @delimiter = delimiter
14
+
15
+ @pg_encoder = PG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter
16
+ @pg_decoder = PG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter
26
17
  end
27
18
 
28
- def type_cast_from_database(value)
19
+ def deserialize(value)
29
20
  if value.is_a?(::String)
30
- type_cast_array(parse_pg_array(value), :type_cast_from_database)
21
+ type_cast_array(@pg_decoder.decode(value), :deserialize)
31
22
  else
32
23
  super
33
24
  end
34
25
  end
35
26
 
36
- def type_cast_from_user(value)
27
+ def cast(value)
37
28
  if value.is_a?(::String)
38
- value = parse_pg_array(value)
29
+ value = @pg_decoder.decode(value)
39
30
  end
40
- type_cast_array(value, :type_cast_from_user)
31
+ type_cast_array(value, :cast)
41
32
  end
42
33
 
43
- def type_cast_for_database(value)
34
+ def serialize(value)
44
35
  if value.is_a?(::Array)
45
- cast_value_for_database(value)
36
+ @pg_encoder.encode(type_cast_array(value, :serialize))
46
37
  else
47
38
  super
48
39
  end
49
40
  end
50
41
 
42
+ def ==(other)
43
+ other.is_a?(Array) &&
44
+ subtype == other.subtype &&
45
+ delimiter == other.delimiter
46
+ end
47
+
48
+ def type_cast_for_schema(value)
49
+ return super unless value.is_a?(::Array)
50
+ "[" + value.map { |v| subtype.type_cast_for_schema(v) }.join(", ") + "]"
51
+ end
52
+
51
53
  private
52
54
 
53
55
  def type_cast_array(value, method)
@@ -57,42 +59,6 @@ module ActiveRecord
57
59
  @subtype.public_send(method, value)
58
60
  end
59
61
  end
60
-
61
- def cast_value_for_database(value)
62
- if value.is_a?(::Array)
63
- casted_values = value.map { |item| cast_value_for_database(item) }
64
- "{#{casted_values.join(delimiter)}}"
65
- else
66
- quote_and_escape(subtype.type_cast_for_database(value))
67
- end
68
- end
69
-
70
- ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
71
-
72
- def quote_and_escape(value)
73
- case value
74
- when ::String
75
- if string_requires_quoting?(value)
76
- value = value.gsub(/\\/, ARRAY_ESCAPE)
77
- value.gsub!(/"/,"\\\"")
78
- %("#{value}")
79
- else
80
- value
81
- end
82
- when nil then "NULL"
83
- when ::Date, ::DateTime, ::Time then subtype.type_cast_for_schema(value)
84
- else value
85
- end
86
- end
87
-
88
- # See http://www.postgresql.org/docs/9.2/static/arrays.html#ARRAYS-IO
89
- # for a list of all cases in which strings will be quoted.
90
- def string_requires_quoting?(string)
91
- string.empty? ||
92
- string == "NULL" ||
93
- string =~ /[\{\}"\\\s]/ ||
94
- string.include?(delimiter)
95
- end
96
62
  end
97
63
  end
98
64
  end
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  :bit
8
8
  end
9
9
 
10
- def type_cast(value)
10
+ def cast(value)
11
11
  if ::String === value
12
12
  case value
13
13
  when /^0x/i
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  end
21
21
  end
22
22
 
23
- def type_cast_for_database(value)
23
+ def serialize(value)
24
24
  Data.new(super) if value
25
25
  end
26
26
 
@@ -3,7 +3,7 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Bytea < Type::Binary # :nodoc:
6
- def type_cast_from_database(value)
6
+ def deserialize(value)
7
7
  return if value.nil?
8
8
  return value.to_s if value.is_a?(Type::Binary::Data)
9
9
  PGconn.unescape_bytea(super)
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  end
19
19
  end
20
20
 
21
- def type_cast_for_database(value)
21
+ def serialize(value)
22
22
  if IPAddr === value
23
23
  "#{value}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
24
24
  else
@@ -3,30 +3,15 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class DateTime < Type::DateTime # :nodoc:
6
- include Infinity
7
-
8
- def type_cast_for_database(value)
9
- if has_precision? && value.acts_like?(:time) && value.year <= 0
10
- bce_year = format("%04d", -value.year + 1)
11
- super.sub(/^-?\d+/, bce_year) + " BC"
12
- else
13
- super
14
- end
15
- end
16
-
17
6
  def cast_value(value)
18
- if value.is_a?(::String)
19
- case value
20
- when 'infinity' then ::Float::INFINITY
21
- when '-infinity' then -::Float::INFINITY
22
- when / BC$/
23
- astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
24
- super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
25
- else
26
- super
27
- end
7
+ case value
8
+ when 'infinity' then ::Float::INFINITY
9
+ when '-infinity' then -::Float::INFINITY
10
+ when / BC$/
11
+ astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
12
+ super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
28
13
  else
29
- value
14
+ super
30
15
  end
31
16
  end
32
17
  end
@@ -3,13 +3,13 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Hstore < Type::Value # :nodoc:
6
- include Type::Mutable
6
+ include Type::Helpers::Mutable
7
7
 
8
8
  def type
9
9
  :hstore
10
10
  end
11
11
 
12
- def type_cast_from_database(value)
12
+ def deserialize(value)
13
13
  if value.is_a?(::String)
14
14
  ::Hash[value.scan(HstorePair).map { |k, v|
15
15
  v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  end
22
22
  end
23
23
 
24
- def type_cast_for_database(value)
24
+ def serialize(value)
25
25
  if value.is_a?(::Hash)
26
26
  value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
27
27
  else
@@ -2,32 +2,7 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
- class Json < Type::Value # :nodoc:
6
- include Type::Mutable
7
-
8
- def type
9
- :json
10
- end
11
-
12
- def type_cast_from_database(value)
13
- if value.is_a?(::String)
14
- ::ActiveSupport::JSON.decode(value) rescue nil
15
- else
16
- super
17
- end
18
- end
19
-
20
- def type_cast_for_database(value)
21
- if value.is_a?(::Array) || value.is_a?(::Hash)
22
- ::ActiveSupport::JSON.encode(value)
23
- else
24
- super
25
- end
26
- end
27
-
28
- def accessor
29
- ActiveRecord::Store::StringKeyedHashAccessor
30
- end
5
+ class Json < Type::Internal::AbstractJson
31
6
  end
32
7
  end
33
8
  end
@@ -9,11 +9,11 @@ module ActiveRecord
9
9
 
10
10
  def changed_in_place?(raw_old_value, new_value)
11
11
  # Postgres does not preserve insignificant whitespaces when
12
- # roundtripping jsonb columns. This causes some false positives for
12
+ # round-tripping jsonb columns. This causes some false positives for
13
13
  # the comparison here. Therefore, we need to parse and re-dump the
14
14
  # raw value here to ensure the insignificant whitespaces are
15
15
  # consistent with our encoder's output.
16
- raw_old_value = type_cast_for_database(type_cast_from_database(raw_old_value))
16
+ raw_old_value = serialize(deserialize(raw_old_value))
17
17
  super(raw_old_value, new_value)
18
18
  end
19
19
  end
@@ -3,8 +3,6 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Money < Type::Decimal # :nodoc:
6
- include Infinity
7
-
8
6
  class_attribute :precision
9
7
 
10
8
  def type
@@ -3,19 +3,19 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Point < Type::Value # :nodoc:
6
- include Type::Mutable
6
+ include Type::Helpers::Mutable
7
7
 
8
8
  def type
9
9
  :point
10
10
  end
11
11
 
12
- def type_cast(value)
12
+ def cast(value)
13
13
  case value
14
14
  when ::String
15
15
  if value[0] == '(' && value[-1] == ')'
16
16
  value = value[1...-1]
17
17
  end
18
- type_cast(value.split(','))
18
+ cast(value.split(','))
19
19
  when ::Array
20
20
  value.map { |v| Float(v) }
21
21
  else
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  end
24
24
  end
25
25
 
26
- def type_cast_for_database(value)
26
+ def serialize(value)
27
27
  if value.is_a?(::Array)
28
28
  "(#{number_for_point(value[0])},#{number_for_point(value[1])})"
29
29
  else
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ Point = Struct.new(:x, :y)
3
+
4
+ module ConnectionAdapters
5
+ module PostgreSQL
6
+ module OID # :nodoc:
7
+ class Rails51Point < Type::Value # :nodoc:
8
+ include Type::Helpers::Mutable
9
+
10
+ def type
11
+ :point
12
+ end
13
+
14
+ def cast(value)
15
+ case value
16
+ when ::String
17
+ if value[0] == '(' && value[-1] == ')'
18
+ value = value[1...-1]
19
+ end
20
+ x, y = value.split(",")
21
+ build_point(x, y)
22
+ when ::Array
23
+ build_point(*value)
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ def serialize(value)
30
+ if value.is_a?(ActiveRecord::Point)
31
+ "(#{number_for_point(value.x)},#{number_for_point(value.y)})"
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def number_for_point(number)
40
+ number.to_s.gsub(/\.0$/, '')
41
+ end
42
+
43
+ def build_point(x, y)
44
+ ActiveRecord::Point.new(Float(x), Float(y))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  class Range < Type::Value # :nodoc:
8
8
  attr_reader :subtype, :type
9
9
 
10
- def initialize(subtype, type)
10
+ def initialize(subtype, type = :range)
11
11
  @subtype = subtype
12
12
  @type = type
13
13
  end
@@ -25,21 +25,12 @@ module ActiveRecord
25
25
  to = type_cast_single extracted[:to]
26
26
 
27
27
  if !infinity?(from) && extracted[:exclude_start]
28
- if from.respond_to?(:succ)
29
- from = from.succ
30
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
31
- Excluding the beginning of a Range is only partialy supported
32
- through `#succ`. This is not reliable and will be removed in
33
- the future.
34
- MSG
35
- else
36
- raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
37
- end
28
+ raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
38
29
  end
39
30
  ::Range.new(from, to, extracted[:exclude_end])
40
31
  end
41
32
 
42
- def type_cast_for_database(value)
33
+ def serialize(value)
43
34
  if value.is_a?(::Range)
44
35
  from = type_cast_single_for_database(value.begin)
45
36
  to = type_cast_single_for_database(value.end)
@@ -49,26 +40,42 @@ module ActiveRecord
49
40
  end
50
41
  end
51
42
 
43
+ def ==(other)
44
+ other.is_a?(Range) &&
45
+ other.subtype == subtype &&
46
+ other.type == type
47
+ end
48
+
52
49
  private
53
50
 
54
51
  def type_cast_single(value)
55
- infinity?(value) ? value : @subtype.type_cast_from_database(value)
52
+ infinity?(value) ? value : @subtype.deserialize(value)
56
53
  end
57
54
 
58
55
  def type_cast_single_for_database(value)
59
- infinity?(value) ? '' : @subtype.type_cast_for_database(value)
56
+ infinity?(value) ? '' : @subtype.serialize(value)
60
57
  end
61
58
 
62
59
  def extract_bounds(value)
63
60
  from, to = value[1..-2].split(',')
64
61
  {
65
- from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
66
- to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
62
+ from: (value[1] == ',' || from == '-infinity') ? infinity(negative: true) : from,
63
+ to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
67
64
  exclude_start: (value[0] == '('),
68
65
  exclude_end: (value[-1] == ')')
69
66
  }
70
67
  end
71
68
 
69
+ def infinity(negative: false)
70
+ if subtype.respond_to?(:infinity)
71
+ subtype.infinity(negative: negative)
72
+ elsif negative
73
+ -::Float::INFINITY
74
+ else
75
+ ::Float::INFINITY
76
+ end
77
+ end
78
+
72
79
  def infinity?(value)
73
80
  value.respond_to?(:infinite?) && value.infinite?
74
81
  end