Skip to content

Commit af4be52

Browse files
authored
Merge pull request rails#44841 from sdrew/ar-point-hash
Add support for ActiveRecord::Point type casts using hash values
2 parents 373dbfd + 1823d4a commit af4be52

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

activerecord/CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
* Add support for `ActiveRecord::Point` type casts using `Hash` values
2+
3+
This allows `ActiveRecord::Point` to be cast or serialized from a hash
4+
with `:x` and `:y` keys of numeric values, mirroring the functionality of
5+
existing casts for string and array values. Both string and symbol keys are
6+
supported.
7+
8+
```ruby
9+
class PostgresqlPoint < ActiveRecord::Base
10+
attribute :x, :point
11+
attribute :y, :point
12+
attribute :z, :point
13+
end
14+
15+
val = PostgresqlPoint.new({
16+
x: '(12.34, -43.21)',
17+
y: [12.34, '-43.21'],
18+
z: {x: '12.34', y: -43.21}
19+
})
20+
ActiveRecord::Point.new(12.32, -43.21) == val.x == val.y == val.z
21+
```
22+
23+
*Stephen Drew*
24+
125
* Replace `SQLite3::Database#busy_timeout` with `#busy_handler_timeout=`.
226

327
Provides a non-GVL-blocking, fair retry interval busy handler implementation.

activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ def cast(value)
2525
build_point(x, y)
2626
when ::Array
2727
build_point(*value)
28+
when ::Hash
29+
return if value.blank?
30+
31+
build_point(*values_array_from_hash(value))
2832
else
2933
value
3034
end
@@ -36,6 +40,8 @@ def serialize(value)
3640
"(#{number_for_point(value.x)},#{number_for_point(value.y)})"
3741
when ::Array
3842
serialize(build_point(*value))
43+
when ::Hash
44+
serialize(build_point(*values_array_from_hash(value)))
3945
else
4046
super
4147
end
@@ -57,6 +63,10 @@ def number_for_point(number)
5763
def build_point(x, y)
5864
ActiveRecord::Point.new(Float(x), Float(y))
5965
end
66+
67+
def values_array_from_hash(value)
68+
[value.values_at(:x, "x").compact.first, value.values_at(:y, "y").compact.first]
69+
end
6070
end
6171
end
6272
end

activerecord/test/cases/adapters/postgresql/geometric_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ def test_array_assignment
8888
assert_equal ActiveRecord::Point.new(1, 2), p.x
8989
end
9090

91+
def test_hash_assignment
92+
p = PostgresqlPoint.new(x: { x: 1, y: 2 }, y: { "x" => 3, "y" => 4 })
93+
94+
assert_equal ActiveRecord::Point.new(1, 2), p.x
95+
assert_equal ActiveRecord::Point.new(3, 4), p.y
96+
end
97+
9198
def test_string_assignment
9299
p = PostgresqlPoint.new(x: "(1, 2)")
93100

0 commit comments

Comments
 (0)