activerecord 5.0.7 → 5.1.7

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 (219) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -2080
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record/aggregations.rb +244 -244
  8. data/lib/active_record/association_relation.rb +5 -5
  9. data/lib/active_record/associations/alias_tracker.rb +10 -11
  10. data/lib/active_record/associations/association.rb +23 -5
  11. data/lib/active_record/associations/association_scope.rb +95 -81
  12. data/lib/active_record/associations/belongs_to_association.rb +7 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +30 -16
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  16. data/lib/active_record/associations/collection_association.rb +36 -205
  17. data/lib/active_record/associations/collection_proxy.rb +132 -63
  18. data/lib/active_record/associations/has_many_association.rb +10 -19
  19. data/lib/active_record/associations/has_many_through_association.rb +12 -4
  20. data/lib/active_record/associations/has_one_association.rb +24 -28
  21. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  22. data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
  23. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  24. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +121 -118
  26. data/lib/active_record/associations/preloader/association.rb +64 -64
  27. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  28. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  29. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  30. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  31. data/lib/active_record/associations/preloader/through_association.rb +41 -41
  32. data/lib/active_record/associations/preloader.rb +94 -94
  33. data/lib/active_record/associations/singular_association.rb +8 -25
  34. data/lib/active_record/associations/through_association.rb +2 -5
  35. data/lib/active_record/associations.rb +1591 -1562
  36. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute_assignment.rb +61 -61
  39. data/lib/active_record/attribute_decorators.rb +35 -13
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +229 -46
  42. data/lib/active_record/attribute_methods/primary_key.rb +74 -73
  43. data/lib/active_record/attribute_methods/read.rb +39 -35
  44. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  46. data/lib/active_record/attribute_methods/write.rb +30 -33
  47. data/lib/active_record/attribute_methods.rb +56 -65
  48. data/lib/active_record/attribute_mutation_tracker.rb +63 -11
  49. data/lib/active_record/attribute_set/builder.rb +27 -33
  50. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  51. data/lib/active_record/attribute_set.rb +9 -6
  52. data/lib/active_record/attributes.rb +22 -22
  53. data/lib/active_record/autosave_association.rb +18 -13
  54. data/lib/active_record/base.rb +24 -22
  55. data/lib/active_record/callbacks.rb +56 -14
  56. data/lib/active_record/coders/yaml_column.rb +9 -11
  57. data/lib/active_record/collection_cache_key.rb +3 -4
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
  70. data/lib/active_record/connection_adapters/column.rb +26 -4
  71. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  72. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  91. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
  92. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
  97. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  99. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
  116. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
  117. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  118. data/lib/active_record/connection_handling.rb +14 -26
  119. data/lib/active_record/core.rb +109 -93
  120. data/lib/active_record/counter_cache.rb +60 -13
  121. data/lib/active_record/define_callbacks.rb +20 -0
  122. data/lib/active_record/dynamic_matchers.rb +80 -79
  123. data/lib/active_record/enum.rb +8 -6
  124. data/lib/active_record/errors.rb +64 -15
  125. data/lib/active_record/explain.rb +1 -2
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +7 -4
  128. data/lib/active_record/fixture_set/file.rb +11 -8
  129. data/lib/active_record/fixtures.rb +66 -53
  130. data/lib/active_record/gem_version.rb +1 -1
  131. data/lib/active_record/inheritance.rb +93 -79
  132. data/lib/active_record/integration.rb +7 -7
  133. data/lib/active_record/internal_metadata.rb +3 -16
  134. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  135. data/lib/active_record/locking/optimistic.rb +69 -74
  136. data/lib/active_record/locking/pessimistic.rb +10 -1
  137. data/lib/active_record/log_subscriber.rb +23 -28
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +100 -47
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/migration.rb +153 -155
  142. data/lib/active_record/model_schema.rb +94 -107
  143. data/lib/active_record/nested_attributes.rb +200 -199
  144. data/lib/active_record/null_relation.rb +11 -34
  145. data/lib/active_record/persistence.rb +65 -50
  146. data/lib/active_record/query_cache.rb +2 -6
  147. data/lib/active_record/querying.rb +3 -4
  148. data/lib/active_record/railtie.rb +16 -17
  149. data/lib/active_record/railties/controller_runtime.rb +6 -2
  150. data/lib/active_record/railties/databases.rake +105 -133
  151. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  152. data/lib/active_record/readonly_attributes.rb +2 -2
  153. data/lib/active_record/reflection.rb +154 -108
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  155. data/lib/active_record/relation/batches.rb +80 -51
  156. data/lib/active_record/relation/calculations.rb +169 -162
  157. data/lib/active_record/relation/delegation.rb +32 -31
  158. data/lib/active_record/relation/finder_methods.rb +197 -231
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  161. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  162. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  163. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  166. data/lib/active_record/relation/predicate_builder.rb +92 -89
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +255 -293
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +80 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/relation.rb +93 -119
  174. data/lib/active_record/result.rb +41 -32
  175. data/lib/active_record/runtime_registry.rb +3 -3
  176. data/lib/active_record/sanitization.rb +176 -192
  177. data/lib/active_record/schema.rb +3 -3
  178. data/lib/active_record/schema_dumper.rb +15 -38
  179. data/lib/active_record/schema_migration.rb +8 -4
  180. data/lib/active_record/scoping/default.rb +90 -90
  181. data/lib/active_record/scoping/named.rb +11 -11
  182. data/lib/active_record/scoping.rb +6 -6
  183. data/lib/active_record/secure_token.rb +2 -2
  184. data/lib/active_record/statement_cache.rb +13 -15
  185. data/lib/active_record/store.rb +31 -32
  186. data/lib/active_record/suppressor.rb +2 -1
  187. data/lib/active_record/table_metadata.rb +9 -5
  188. data/lib/active_record/tasks/database_tasks.rb +65 -55
  189. data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
  190. data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
  191. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  192. data/lib/active_record/timestamp.rb +46 -25
  193. data/lib/active_record/touch_later.rb +1 -2
  194. data/lib/active_record/transactions.rb +97 -109
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +13 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/internal/abstract_json.rb +4 -0
  199. data/lib/active_record/type/serialized.rb +14 -8
  200. data/lib/active_record/type/text.rb +9 -0
  201. data/lib/active_record/type/time.rb +0 -1
  202. data/lib/active_record/type/type_map.rb +11 -15
  203. data/lib/active_record/type/unsigned_integer.rb +15 -0
  204. data/lib/active_record/type.rb +17 -13
  205. data/lib/active_record/type_caster/connection.rb +8 -6
  206. data/lib/active_record/type_caster/map.rb +3 -1
  207. data/lib/active_record/type_caster.rb +2 -2
  208. data/lib/active_record/validations/associated.rb +1 -1
  209. data/lib/active_record/validations/presence.rb +2 -2
  210. data/lib/active_record/validations/uniqueness.rb +8 -39
  211. data/lib/active_record/validations.rb +4 -4
  212. data/lib/active_record/version.rb +1 -1
  213. data/lib/active_record.rb +20 -20
  214. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  215. data/lib/rails/generators/active_record/migration.rb +1 -1
  216. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  217. data/lib/rails/generators/active_record.rb +4 -4
  218. metadata +24 -13
  219. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -34,16 +34,18 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  def binary?
37
- /\A[01]*\Z/ === value
37
+ /\A[01]*\Z/.match?(value)
38
38
  end
39
39
 
40
40
  def hex?
41
- /\A[0-9A-F]*\Z/i === value
41
+ /\A[0-9A-F]*\Z/i.match?(value)
42
42
  end
43
43
 
44
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
45
+ # Workaround for Ruby 2.2 "private attribute?" warning.
44
46
  protected
45
47
 
46
- attr_reader :value
48
+ attr_reader :value
47
49
  end
48
50
  end
49
51
  end
@@ -1,4 +1,4 @@
1
- require 'ipaddr'
1
+ require "ipaddr"
2
2
 
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
@@ -5,8 +5,8 @@ module ActiveRecord
5
5
  class DateTime < Type::DateTime # :nodoc:
6
6
  def cast_value(value)
7
7
  case value
8
- when 'infinity' then ::Float::INFINITY
9
- when '-infinity' then -::Float::INFINITY
8
+ when "infinity" then ::Float::INFINITY
9
+ when "-infinity" then -::Float::INFINITY
10
10
  when / BC$/
11
11
  astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
12
12
  super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module OID # :nodoc:
5
5
  class Decimal < Type::Decimal # :nodoc:
6
6
  def infinity(options = {})
7
- BigDecimal.new("Infinity") * (options[:negative] ? -1 : 1)
7
+ BigDecimal("Infinity") * (options[:negative] ? -1 : 1)
8
8
  end
9
9
  end
10
10
  end
@@ -9,9 +9,9 @@ module ActiveRecord
9
9
 
10
10
  private
11
11
 
12
- def cast_value(value)
13
- value.to_s
14
- end
12
+ def cast_value(value)
13
+ value.to_s
14
+ end
15
15
  end
16
16
  end
17
17
  end
@@ -12,8 +12,8 @@ module ActiveRecord
12
12
  def deserialize(value)
13
13
  if value.is_a?(::String)
14
14
  ::Hash[value.scan(HstorePair).map { |k, v|
15
- v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
16
- k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
15
+ v = v.upcase == "NULL" ? nil : v.gsub(/\A"(.*)"\Z/m, '\1').gsub(/\\(.)/, '\1')
16
+ k = k.gsub(/\A"(.*)"\Z/m, '\1').gsub(/\\(.)/, '\1')
17
17
  [k, v]
18
18
  }]
19
19
  else
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
 
24
24
  def serialize(value)
25
25
  if value.is_a?(::Hash)
26
- value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
26
+ value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(", ")
27
27
  elsif value.respond_to?(:to_unsafe_h)
28
28
  serialize(value.to_unsafe_h)
29
29
  else
@@ -45,23 +45,23 @@ module ActiveRecord
45
45
 
46
46
  private
47
47
 
48
- HstorePair = begin
49
- quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
50
- unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
51
- /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
52
- end
48
+ HstorePair = begin
49
+ quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
50
+ unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
51
+ /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
52
+ end
53
53
 
54
- def escape_hstore(value)
55
- if value.nil?
56
- 'NULL'
57
- else
58
- if value == ""
59
- '""'
54
+ def escape_hstore(value)
55
+ if value.nil?
56
+ "NULL"
60
57
  else
61
- '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
58
+ if value == ""
59
+ '""'
60
+ else
61
+ '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
62
+ end
62
63
  end
63
64
  end
64
- end
65
65
  end
66
66
  end
67
67
  end
@@ -6,16 +6,6 @@ module ActiveRecord
6
6
  def type
7
7
  :jsonb
8
8
  end
9
-
10
- def changed_in_place?(raw_old_value, new_value)
11
- # Postgres does not preserve insignificant whitespaces when
12
- # round-tripping jsonb columns. This causes some false positives for
13
- # the comparison here. Therefore, we need to parse and re-dump the
14
- # raw value here to ensure the insignificant whitespaces are
15
- # consistent with our encoder's output.
16
- raw_old_value = serialize(deserialize(raw_old_value))
17
- super(raw_old_value, new_value)
18
- end
19
9
  end
20
10
  end
21
11
  end
@@ -1,10 +1,8 @@
1
1
  module ActiveRecord
2
- Point = Struct.new(:x, :y)
3
-
4
2
  module ConnectionAdapters
5
3
  module PostgreSQL
6
4
  module OID # :nodoc:
7
- class Rails51Point < Type::Value # :nodoc:
5
+ class LegacyPoint < Type::Value # :nodoc:
8
6
  include Type::Helpers::Mutable
9
7
 
10
8
  def type
@@ -14,21 +12,20 @@ module ActiveRecord
14
12
  def cast(value)
15
13
  case value
16
14
  when ::String
17
- if value[0] == '(' && value[-1] == ')'
15
+ if value[0] == "(" && value[-1] == ")"
18
16
  value = value[1...-1]
19
17
  end
20
- x, y = value.split(",")
21
- build_point(x, y)
18
+ cast(value.split(","))
22
19
  when ::Array
23
- build_point(*value)
20
+ value.map { |v| Float(v) }
24
21
  else
25
22
  value
26
23
  end
27
24
  end
28
25
 
29
26
  def serialize(value)
30
- if value.is_a?(ActiveRecord::Point)
31
- "(#{number_for_point(value.x)},#{number_for_point(value.y)})"
27
+ if value.is_a?(::Array)
28
+ "(#{number_for_point(value[0])},#{number_for_point(value[1])})"
32
29
  else
33
30
  super
34
31
  end
@@ -36,13 +33,9 @@ module ActiveRecord
36
33
 
37
34
  private
38
35
 
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
36
+ def number_for_point(number)
37
+ number.to_s.gsub(/\.0$/, "")
38
+ end
46
39
  end
47
40
  end
48
41
  end
@@ -25,9 +25,9 @@ module ActiveRecord
25
25
  value.sub!(/^\((.+)\)$/, '-\1') # (4)
26
26
  case value
27
27
  when /^-?\D+[\d,]+\.\d{2}$/ # (1)
28
- value.gsub!(/[^-\d.]/, '')
28
+ value.gsub!(/[^-\d.]/, "")
29
29
  when /^-?\D+[\d.]+,\d{2}$/ # (2)
30
- value.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
30
+ value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
31
31
  end
32
32
 
33
33
  super(value)
@@ -0,0 +1,13 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostgreSQL
4
+ module OID # :nodoc:
5
+ class Oid < Type::Integer # :nodoc:
6
+ def type
7
+ :oid
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,6 @@
1
1
  module ActiveRecord
2
+ Point = Struct.new(:x, :y)
3
+
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module OID # :nodoc:
@@ -12,20 +14,34 @@ module ActiveRecord
12
14
  def cast(value)
13
15
  case value
14
16
  when ::String
15
- if value[0] == '(' && value[-1] == ')'
17
+ return if value.blank?
18
+
19
+ if value[0] == "(" && value[-1] == ")"
16
20
  value = value[1...-1]
17
21
  end
18
- cast(value.split(','))
22
+ x, y = value.split(",")
23
+ build_point(x, y)
19
24
  when ::Array
20
- value.map { |v| Float(v) }
25
+ build_point(*value)
21
26
  else
22
27
  value
23
28
  end
24
29
  end
25
30
 
26
31
  def serialize(value)
27
- if value.is_a?(::Array)
28
- "(#{number_for_point(value[0])},#{number_for_point(value[1])})"
32
+ case value
33
+ when ActiveRecord::Point
34
+ "(#{number_for_point(value.x)},#{number_for_point(value.y)})"
35
+ when ::Array
36
+ serialize(build_point(*value))
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def type_cast_for_schema(value)
43
+ if ActiveRecord::Point === value
44
+ [value.x, value.y]
29
45
  else
30
46
  super
31
47
  end
@@ -33,9 +49,13 @@ module ActiveRecord
33
49
 
34
50
  private
35
51
 
36
- def number_for_point(number)
37
- number.to_s.gsub(/\.0$/, '')
38
- end
52
+ def number_for_point(number)
53
+ number.to_s.gsub(/\.0$/, "")
54
+ end
55
+
56
+ def build_point(x, y)
57
+ ActiveRecord::Point.new(Float(x), Float(y))
58
+ end
39
59
  end
40
60
  end
41
61
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/string/filters'
2
-
3
1
  module ActiveRecord
4
2
  module ConnectionAdapters
5
3
  module PostgreSQL
@@ -14,11 +12,11 @@ module ActiveRecord
14
12
  end
15
13
 
16
14
  def type_cast_for_schema(value)
17
- value.inspect.gsub('Infinity', '::Float::INFINITY')
15
+ value.inspect.gsub("Infinity", "::Float::INFINITY")
18
16
  end
19
17
 
20
18
  def cast_value(value)
21
- return if value == 'empty'
19
+ return if value == "empty"
22
20
  return value unless value.is_a?(::String)
23
21
 
24
22
  extracted = extract_bounds(value)
@@ -53,39 +51,43 @@ module ActiveRecord
53
51
  ::Range.new(new_begin, new_end, value.exclude_end?)
54
52
  end
55
53
 
54
+ def force_equality?(value)
55
+ value.is_a?(::Range)
56
+ end
57
+
56
58
  private
57
59
 
58
- def type_cast_single(value)
59
- infinity?(value) ? value : @subtype.deserialize(value)
60
- end
60
+ def type_cast_single(value)
61
+ infinity?(value) ? value : @subtype.deserialize(value)
62
+ end
61
63
 
62
- def type_cast_single_for_database(value)
63
- infinity?(value) ? '' : @subtype.serialize(value)
64
- end
64
+ def type_cast_single_for_database(value)
65
+ infinity?(value) ? "" : @subtype.serialize(value)
66
+ end
65
67
 
66
- def extract_bounds(value)
67
- from, to = value[1..-2].split(',')
68
- {
69
- from: (value[1] == ',' || from == '-infinity') ? infinity(negative: true) : from,
70
- to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
71
- exclude_start: (value[0] == '('),
72
- exclude_end: (value[-1] == ')')
73
- }
74
- end
68
+ def extract_bounds(value)
69
+ from, to = value[1..-2].split(",")
70
+ {
71
+ from: (value[1] == "," || from == "-infinity") ? infinity(negative: true) : from,
72
+ to: (value[-2] == "," || to == "infinity") ? infinity : to,
73
+ exclude_start: (value[0] == "("),
74
+ exclude_end: (value[-1] == ")")
75
+ }
76
+ end
75
77
 
76
- def infinity(negative: false)
77
- if subtype.respond_to?(:infinity)
78
- subtype.infinity(negative: negative)
79
- elsif negative
80
- -::Float::INFINITY
81
- else
82
- ::Float::INFINITY
78
+ def infinity(negative: false)
79
+ if subtype.respond_to?(:infinity)
80
+ subtype.infinity(negative: negative)
81
+ elsif negative
82
+ -::Float::INFINITY
83
+ else
84
+ ::Float::INFINITY
85
+ end
83
86
  end
84
- end
85
87
 
86
- def infinity?(value)
87
- value.respond_to?(:infinite?) && value.infinite?
88
- end
88
+ def infinity?(value)
89
+ value.respond_to?(:infinite?) && value.infinite?
90
+ end
89
91
  end
90
92
  end
91
93
  end
@@ -5,8 +5,9 @@ module ActiveRecord
5
5
  class SpecializedString < Type::String # :nodoc:
6
6
  attr_reader :type
7
7
 
8
- def initialize(type)
8
+ def initialize(type, **options)
9
9
  @type = type
10
+ super(options)
10
11
  end
11
12
  end
12
13
  end
@@ -13,13 +13,13 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def run(records)
16
- nodes = records.reject { |row| @store.key? row['oid'].to_i }
17
- mapped, nodes = nodes.partition { |row| @store.key? row['typname'] }
18
- ranges, nodes = nodes.partition { |row| row['typtype'] == 'r'.freeze }
19
- enums, nodes = nodes.partition { |row| row['typtype'] == 'e'.freeze }
20
- domains, nodes = nodes.partition { |row| row['typtype'] == 'd'.freeze }
21
- arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in'.freeze }
22
- composites, nodes = nodes.partition { |row| row['typelem'].to_i != 0 }
16
+ nodes = records.reject { |row| @store.key? row["oid"].to_i }
17
+ mapped, nodes = nodes.partition { |row| @store.key? row["typname"] }
18
+ ranges, nodes = nodes.partition { |row| row["typtype"] == "r".freeze }
19
+ enums, nodes = nodes.partition { |row| row["typtype"] == "e".freeze }
20
+ domains, nodes = nodes.partition { |row| row["typtype"] == "d".freeze }
21
+ arrays, nodes = nodes.partition { |row| row["typinput"] == "array_in".freeze }
22
+ composites, nodes = nodes.partition { |row| row["typelem"].to_i != 0 }
23
23
 
24
24
  mapped.each { |row| register_mapped_type(row) }
25
25
  enums.each { |row| register_enum_type(row) }
@@ -42,66 +42,66 @@ module ActiveRecord
42
42
  end
43
43
 
44
44
  private
45
- def register_mapped_type(row)
46
- alias_type row['oid'], row['typname']
47
- end
45
+ def register_mapped_type(row)
46
+ alias_type row["oid"], row["typname"]
47
+ end
48
48
 
49
- def register_enum_type(row)
50
- register row['oid'], OID::Enum.new
51
- end
49
+ def register_enum_type(row)
50
+ register row["oid"], OID::Enum.new
51
+ end
52
52
 
53
- def register_array_type(row)
54
- register_with_subtype(row['oid'], row['typelem'].to_i) do |subtype|
55
- OID::Array.new(subtype, row['typdelim'])
53
+ def register_array_type(row)
54
+ register_with_subtype(row["oid"], row["typelem"].to_i) do |subtype|
55
+ OID::Array.new(subtype, row["typdelim"])
56
+ end
56
57
  end
57
- end
58
58
 
59
- def register_range_type(row)
60
- register_with_subtype(row['oid'], row['rngsubtype'].to_i) do |subtype|
61
- OID::Range.new(subtype, row['typname'].to_sym)
59
+ def register_range_type(row)
60
+ register_with_subtype(row["oid"], row["rngsubtype"].to_i) do |subtype|
61
+ OID::Range.new(subtype, row["typname"].to_sym)
62
+ end
62
63
  end
63
- end
64
64
 
65
- def register_domain_type(row)
66
- if base_type = @store.lookup(row["typbasetype"].to_i)
67
- register row['oid'], base_type
68
- else
69
- warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
65
+ def register_domain_type(row)
66
+ if base_type = @store.lookup(row["typbasetype"].to_i)
67
+ register row["oid"], base_type
68
+ else
69
+ warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
70
+ end
70
71
  end
71
- end
72
72
 
73
- def register_composite_type(row)
74
- if subtype = @store.lookup(row['typelem'].to_i)
75
- register row['oid'], OID::Vector.new(row['typdelim'], subtype)
73
+ def register_composite_type(row)
74
+ if subtype = @store.lookup(row["typelem"].to_i)
75
+ register row["oid"], OID::Vector.new(row["typdelim"], subtype)
76
+ end
76
77
  end
77
- end
78
78
 
79
- def register(oid, oid_type = nil, &block)
80
- oid = assert_valid_registration(oid, oid_type || block)
81
- if block_given?
82
- @store.register_type(oid, &block)
83
- else
84
- @store.register_type(oid, oid_type)
79
+ def register(oid, oid_type = nil, &block)
80
+ oid = assert_valid_registration(oid, oid_type || block)
81
+ if block_given?
82
+ @store.register_type(oid, &block)
83
+ else
84
+ @store.register_type(oid, oid_type)
85
+ end
85
86
  end
86
- end
87
87
 
88
- def alias_type(oid, target)
89
- oid = assert_valid_registration(oid, target)
90
- @store.alias_type(oid, target)
91
- end
88
+ def alias_type(oid, target)
89
+ oid = assert_valid_registration(oid, target)
90
+ @store.alias_type(oid, target)
91
+ end
92
92
 
93
- def register_with_subtype(oid, target_oid)
94
- if @store.key?(target_oid)
95
- register(oid) do |_, *args|
96
- yield @store.lookup(target_oid, *args)
93
+ def register_with_subtype(oid, target_oid)
94
+ if @store.key?(target_oid)
95
+ register(oid) do |_, *args|
96
+ yield @store.lookup(target_oid, *args)
97
+ end
97
98
  end
98
99
  end
99
- end
100
100
 
101
- def assert_valid_registration(oid, oid_type)
102
- raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
103
- oid.to_i
104
- end
101
+ def assert_valid_registration(oid, oid_type)
102
+ raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
103
+ oid.to_i
104
+ end
105
105
  end
106
106
  end
107
107
  end
@@ -1,25 +1,26 @@
1
- require 'active_record/connection_adapters/postgresql/oid/array'
2
- require 'active_record/connection_adapters/postgresql/oid/bit'
3
- require 'active_record/connection_adapters/postgresql/oid/bit_varying'
4
- require 'active_record/connection_adapters/postgresql/oid/bytea'
5
- require 'active_record/connection_adapters/postgresql/oid/cidr'
6
- require 'active_record/connection_adapters/postgresql/oid/date_time'
7
- require 'active_record/connection_adapters/postgresql/oid/decimal'
8
- require 'active_record/connection_adapters/postgresql/oid/enum'
9
- require 'active_record/connection_adapters/postgresql/oid/hstore'
10
- require 'active_record/connection_adapters/postgresql/oid/inet'
11
- require 'active_record/connection_adapters/postgresql/oid/json'
12
- require 'active_record/connection_adapters/postgresql/oid/jsonb'
13
- require 'active_record/connection_adapters/postgresql/oid/money'
14
- require 'active_record/connection_adapters/postgresql/oid/point'
15
- require 'active_record/connection_adapters/postgresql/oid/rails_5_1_point'
16
- require 'active_record/connection_adapters/postgresql/oid/range'
17
- require 'active_record/connection_adapters/postgresql/oid/specialized_string'
18
- require 'active_record/connection_adapters/postgresql/oid/uuid'
19
- require 'active_record/connection_adapters/postgresql/oid/vector'
20
- require 'active_record/connection_adapters/postgresql/oid/xml'
1
+ require "active_record/connection_adapters/postgresql/oid/array"
2
+ require "active_record/connection_adapters/postgresql/oid/bit"
3
+ require "active_record/connection_adapters/postgresql/oid/bit_varying"
4
+ require "active_record/connection_adapters/postgresql/oid/bytea"
5
+ require "active_record/connection_adapters/postgresql/oid/cidr"
6
+ require "active_record/connection_adapters/postgresql/oid/date_time"
7
+ require "active_record/connection_adapters/postgresql/oid/decimal"
8
+ require "active_record/connection_adapters/postgresql/oid/enum"
9
+ require "active_record/connection_adapters/postgresql/oid/hstore"
10
+ require "active_record/connection_adapters/postgresql/oid/inet"
11
+ require "active_record/connection_adapters/postgresql/oid/json"
12
+ require "active_record/connection_adapters/postgresql/oid/jsonb"
13
+ require "active_record/connection_adapters/postgresql/oid/money"
14
+ require "active_record/connection_adapters/postgresql/oid/oid"
15
+ require "active_record/connection_adapters/postgresql/oid/point"
16
+ require "active_record/connection_adapters/postgresql/oid/legacy_point"
17
+ require "active_record/connection_adapters/postgresql/oid/range"
18
+ require "active_record/connection_adapters/postgresql/oid/specialized_string"
19
+ require "active_record/connection_adapters/postgresql/oid/uuid"
20
+ require "active_record/connection_adapters/postgresql/oid/vector"
21
+ require "active_record/connection_adapters/postgresql/oid/xml"
21
22
 
22
- require 'active_record/connection_adapters/postgresql/oid/type_map_initializer'
23
+ require "active_record/connection_adapters/postgresql/oid/type_map_initializer"
23
24
 
24
25
  module ActiveRecord
25
26
  module ConnectionAdapters