-
-
Notifications
You must be signed in to change notification settings - Fork 255
Compatibility with Rails 8.1 #435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| # has_z: false | ||
| # has_m: false | ||
| def self.parse_sql_type(sql_type) | ||
| # Could be nil during type registration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not entirely sure why this happens as I'm not fully familiar with active record internals, but this seems to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm investigating it these days on crdb adapter, I hope I'll come with more information and a clean solution soonish :) (before the end of this month)
|
|
||
| def spatial_factory | ||
| @spatial_factory ||= | ||
| if frozen? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debated on this branch for a bit, not sure when this object would be unfrozen now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should see if there is a performance a space change, but I'd rather bubble that back up to the initialiser than create a factory every time. Also the if frozen? branch is useless since the goal of ractor compatibility for types as I understood is to have them frozen all the time !
|
There are more changed required to have the adapter working. For this reason, i decided to create an extension instead of legacy way of having a pg adapter.. My goal is to move that repo later to this organization. The interface is plug & play. |
|
Actually looking at the failed tests, they seem to all be from the ActiveRecord test suite itself. Is there a reason why the gem runs the tests for Rails? |
|
let upgrade to test with rc1 |
- Handle `cast_type` being the second parameter for `SpatialColumn.initialize`. - Handle nil case during OID initiation. - Handle case where in `spatial_factory` the object could be frozen for whatever reason. - Update CI to test against 8.1 and supported PG and Rubies.
5f6e071 to
6b0af9e
Compare
Gemfile
Outdated
| gem "pg", "~> 1.0", platform: :ruby | ||
| gem "byebug" if ENV["BYEBUG"] | ||
|
|
||
| gem "rgeo-activerecord", git: "https://github.com/rgeo/rgeo-activerecord.git" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting!
Do rgeo need any release ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I had a PR for 8.1 support merged a few weeks ago..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On it now ! Thank you for the PR
I found a solution for that in the 8.1 crdb adapter update cockroachdb/activerecord-cockroachdb-adapter@e656a24.
Running rails test suite ensure a complete coverage that we would not have with only our own test suite, and helps us make sure that we implement all API changes from the rails release we are bumping to |
|
Current state of things: Locally, tests should pass now with the inclusion of those backtrace fixes. I removed the I tried moving that logic into the initializer, but ran into two issues:
|
|
Looks like the runners that failed all failed on the same error. Which is an ActiveRecord test for fixtures. Possibly a flakey test? |
.github/workflows/tests.yml
Outdated
| ruby: ["3.4", "3.3", "3.2"] | ||
| # https://www.postgresql.org/support/versioning/ | ||
| pg: [12-master, 13-master, 14-master, 15-master, 16-master] | ||
| pg: [13-master, 14-master, 15-master, 16-master, 17-master] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pg 18 was released a month ago is there a reason not to include it here? my fault, this pr went up before it came out. still might be nice to add here though.
|
I'm a little confused... @t27duck is the path forward to adopt the new gem that @seuros is proposing (whereby the pg adapter is extended rather than replaced), or to bring in Rails 8.1 compatibility with this gem? We're blocked on our upgrade and would love assistance/guidance on where to go with this issue. |
This plan has not been discussed by maintainers of the gem, you'd have to ask @seuros. As far as I'm concern, I'd rather keep this gem. I'm currently working on rails compatibility for the CRDB adapter, once done I'll have time to handle this more properly. In the mean time, you can point to this branch. The differences are usually in some deep functionnalities and you're unlikely to have problems. And if you do, please report them here.
You can talk to your company about RGeo's open-collective and financing. Or directly hire me as a freelance if you need fast-paced guidance and proper deadlines. Otherwise, as we're few to maintain on our spare time, I cannot give you deadlines. |
|
@BuonOmo Actually i did send email to both you and @keithdoggett in 2024 i think. I did have a back and forth with Keith. My plan was to create it and transfer it to this org. I assumed you were in the same line as what Keith said, to keep this architecture. activerecord-postgis-adapter is an inherited adapter. I contributed to it when It was just basically a copy carbon the upstream adapter. I did raise my concern that one day it will be good have it extending AR instead of forking. activerecord-postgis is that wish but as reality, different archirecture, same api. I had that gem vendored for my needs since rails 7.0. but it had no README and was missing feature i didn't use. I contributed to this adapter, because i knew upgrade it, not because i needed the upgrade. When i released activerecord-postgis, i posted it in reddit, X, HN, and i got immediately hammered by Anti-AI people telling me that i vibed it and that it not how it should be made. They didn't try it or reviewed the code. They see Claude and emojis in readme... They went full tribal ape on me. The moderators deleted the post after it went -40 and subject became about AI slop. My tweet still up, but with minimal engagement. activerecord-postgis is the exact copy of this gem(api-wise), the underline Activerecord logic is from rgeo org. |
Never received it sorry, do you have the correct email ? buonomo dot ulysse at gmail dot com.
No-go for me, we're not a team large enough to handle such a transition, see all of the open issues and the time to upgrade to rails 8.1 as an indicator. I'm not taking one more project. I'd eventually be alright with mentioning it as an existing alternative in the README, if it is not a drop-and-replace but an alternative for a different use case.
I have a hard time understanding your point here. We already extend the PG adapter, which IMHO is a pretty correct way of doing. We don't copy, and I tend to try to patch rather than copy paste methods as much as I can, and would like to keep going in that direction.
You posted what?
Which post? About what topic? I have a bit of a tough time understanding the problems you are raising and how those are linked to your new gems.
Damn that's not cool. I really hope we can work out something that work for you as well. I'm all up for having a bigger team here, with better organisation. |
The alternative gem is a 99% drop-in replacement. The only difference is in annotation output and the use of postgresql:// instead of postgis://. (If you replace it and don’t fix the adapter or DATABASE_URL, it will crash.) My point is that I’ve been involved with this gem since the days when dazuma (the original author) was still maintaining it. Then came another era with Tee Perham, and we did a big refactor to inherit from the adapter, renamed columns to avoid conflicts with PostgreSQL internal types once Active Record started using them, that’s the current structure of this gem.
I posted about the other gem in social media 'Announcing activerecord-postgis, a drop-in replacement...' It got immediate downvotes and insults by email. (Most of them don’t even use Postgres or know what a spatial database is... maybe they thought I forked NASA or SpaceX.) I’m fine with just having a mention in the README for now. But my goal is for the other gem to eventually take this one’s place. I can maintain it, it’s smaller, cleaner, and has more tests. My only concern with solo maintenance is that it might work fine for my use case but break for others. Just to give you an example: before open-sourcing it, I had a hardcoded SRID. That works when I control the architecture, but I can’t open-source it and force everyone to use a single SRID. We need to get this PR green to ship. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked locally, the failure are just timing related. ![]()
I just checked again for the keywords
My other concern would also be that the day you decide to stop working on it, the whole community loses the gem... At least here we're two maintainers, and a few active developers.
Could you maybe make an issue in this repo explaining the main axes of differences and how we could refactor to get to an ideal place that keeps steps made here, history and still take advantage of the new rails architecture?
What do you mean? I believe there is still the ractor issue that we need to either tackle or create an issue for. And about the failing tests, if by timing you mean that they depend on test order, that is still not green IMHO. I've been using EDIT: I've also taken the time to look at your new adapter, and I see two main issues that make it a no go for me:
I'm not done with the review, this is quite a heavy chunk. But I can see the pieces we could migrate to this codebase, which would be nice. |
That exactly why i asked it to move it to I use the gem heavily, i did not see any regression. |
Then users can point to this branch with some sense of security. I would still focus on fixing tests and make sure ractor compatibility is correct. I would be okay with having an
Well, I'm up to opening PRs here to migrate some parts of your code (for instance the arel part, but I'm sure you know of others that would make sense). I still am against patching pg adapter and think we should rather inherit (as mentioned above), but that could be up for discussion. |
|
@BuonOmo I did get the email and responded, though did not have much time and didn't continue the discussion (sorry @seuros ). I have similar concerns to you. Primarily having 2 repos that serve similar purposes and communicating to all users to move to a new gem seemed daunting given the limited time we have already. I do agree with your idea of trying to merge the improvements into this though and eventually "converting" this repo if we like the changes. WRT this PR, looking at potentially rewriting that test internally to ensure the db structure is the same. I see other test cases where a prefix or postfix is added to the table and then it's modified. Not clear why it's affecting the unmodified table. Would love to find a better solution but at this point might be best to try to get passing tests and merge this. |
|
Hey @t27duck, I've added a patch to your PR to be ractor shareable, fix two untested bugs and a bit of miscellaneous stuff. Could you allow edits by maintainers ? Otherwise here's the patch (but I'd likely need to push more of it!): commit 6c561b733741b76812f19462f7f433e135e964ba
Author: Ulysse Buonomo <[email protected]>
Date: Fri Nov 21 19:41:09 2025 +0100
Import changes from CRDB adapter
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index a3d7431..fa03d10 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -39,14 +39,14 @@ jobs:
--health-timeout 5s
--health-retries 5
env:
- AR_VERSION: 8.1.0
+ AR_VERSION: 8.1.1
strategy:
fail-fast: false
matrix:
# https://ruby-lang.org/en/downloads/branches
ruby: ["3.4", "3.3", "3.2"]
# https://www.postgresql.org/support/versioning/
- pg: [13-master, 14-master, 15-master, 16-master, 17-master]
+ pg: [14-master, 15-master, 16-master, 17-master, 18-master]
steps:
- name: Set Up Actions
uses: actions/checkout@v4
diff --git a/Gemfile b/Gemfile
index 337f673..5976f20 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,8 +6,6 @@ gemspec
gem "pg", "~> 1.0", platform: :ruby
gem "byebug" if ENV["BYEBUG"]
-gem "rgeo-activerecord", git: "https://github.com/rgeo/rgeo-activerecord.git"
-
def activerecord_version
return ENV["AR_VERSION"] if ENV["AR_VERSION"]
diff --git a/activerecord-postgis-adapter.gemspec b/activerecord-postgis-adapter.gemspec
index 7f83e83..6174e12 100644
--- a/activerecord-postgis-adapter.gemspec
+++ b/activerecord-postgis-adapter.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 3.2.0"
spec.add_dependency "activerecord", "~> 8.1.0"
- spec.add_dependency "rgeo-activerecord"
+ spec.add_dependency "rgeo-activerecord", "~> 8.1.0"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "minitest", "~> 5.4"
diff --git a/lib/active_record/connection_adapters/postgis/spatial_column.rb b/lib/active_record/connection_adapters/postgis/column.rb
similarity index 71%
rename from lib/active_record/connection_adapters/postgis/spatial_column.rb
rename to lib/active_record/connection_adapters/postgis/column.rb
index ea50d69..bb4d64d 100644
--- a/lib/active_record/connection_adapters/postgis/spatial_column.rb
+++ b/lib/active_record/connection_adapters/postgis/column.rb
@@ -3,14 +3,15 @@
module ActiveRecord # :nodoc:
module ConnectionAdapters # :nodoc:
module PostGIS # :nodoc:
- class SpatialColumn < ConnectionAdapters::PostgreSQLColumn # :nodoc:
+ class Column < PostgreSQL::Column # :nodoc:
# sql_type examples:
# "Geometry(Point,4326)"
# "Geography(Point,4326)"
def initialize(name, cast_type, default, sql_type_metadata = nil, null = true,
default_function = nil, collation: nil, comment: nil,
serial: nil, generated: nil, spatial: nil, identity: nil)
- @sql_type_metadata = sql_type_metadata
+ super(name, cast_type, default, sql_type_metadata, null, default_function,
+ collation: collation, comment: comment, serial: serial, generated: generated, identity: identity)
@geographic = !!(sql_type_metadata.sql_type =~ /geography\(/i)
if spatial
# This case comes from an entry in the geometry_columns table
@@ -30,8 +31,6 @@ module ActiveRecord # :nodoc:
# @geometric_type = geo_type_from_sql_type(sql_type)
build_from_sql_type(sql_type_metadata.sql_type)
end
- super(name, cast_type, default, sql_type_metadata, null, default_function,
- collation: collation, comment: comment, serial: serial, generated: generated, identity: identity)
if spatial? && @srid
@limit = { srid: @srid, type: to_type_name(geometric_type) }
@limit[:has_z] = true if @has_z
@@ -58,6 +57,49 @@ module ActiveRecord # :nodoc:
%i[geometry geography].include?(@sql_type_metadata.type)
end
+ def init_with(coder)
+ @geographic = coder["geographic"]
+ @geometric_type = coder["geometric_type"]
+ @has_m = coder["has_m"]
+ @has_z = coder["has_z"]
+ @srid = coder["srid"]
+ @limit = coder["limit"]
+ super
+ end
+
+ def encode_with(coder)
+ coder["geographic"] = @geographic
+ coder["geometric_type"] = @geometric_type
+ coder["has_m"] = @has_m
+ coder["has_z"] = @has_z
+ coder["srid"] = @srid
+ coder["limit"] = @limit
+ super
+ end
+
+ def ==(other)
+ other.is_a?(Column) &&
+ super &&
+ other.geographic == geographic &&
+ other.geometric_type == geometric_type &&
+ other.has_m == has_m &&
+ other.has_z == has_z &&
+ other.srid == srid &&
+ other.limit == limit
+ end
+ alias :eql? :==
+
+ def hash
+ Column.hash ^
+ super.hash ^
+ geographic.hash ^
+ geometric_type.hash ^
+ has_m.hash ^
+ has_z.hash ^
+ srid.hash ^
+ limit.hash
+ end
+
private
def set_geometric_type_from_name(name)
diff --git a/lib/active_record/connection_adapters/postgis/oid/spatial.rb b/lib/active_record/connection_adapters/postgis/oid/spatial.rb
index 135dd29..d44c933 100644
--- a/lib/active_record/connection_adapters/postgis/oid/spatial.rb
+++ b/lib/active_record/connection_adapters/postgis/oid/spatial.rb
@@ -11,12 +11,16 @@ module ActiveRecord
class Spatial < Type::Value
def initialize(geo_type: "geometry", srid: 0, has_z: false, has_m: false, geographic: false)
super()
- @geo_type = geo_type
- @srid = srid
- @has_z = has_z
- @has_m = has_m
- @geographic = geographic
+ @geographic = geographic.freeze
+ @factory_attrs = {
+ geo_type: geo_type.underscore.freeze,
+ has_m: has_m.freeze,
+ has_z: has_z.freeze,
+ srid: srid.freeze,
+ sql_type: type.to_s.freeze
+ }.freeze
end
+ protected attr_reader :geographic, :factory_attrs
# sql_type: geometry, geometry(Point), geometry(Point,4326), ...
#
@@ -26,11 +30,6 @@ module ActiveRecord
# has_z: false
# has_m: false
def self.parse_sql_type(sql_type)
- # Could be nil during type registration
- if sql_type.nil?
- return [nil, 0, false, false, false]
- end
-
geo_type = nil
srid = 0
has_z = false
@@ -85,6 +84,17 @@ module ActiveRecord
.generate(geo_value)
end
+ def ==(other)
+ super &&
+ @geographic == other.geographic &&
+ @factory_attrs == other.factory_attrs
+ end
+ alias eql? ==
+
+ def hash
+ super ^ [@geographic, @factory_attrs].hash
+ end
+
private
def cast_value(value)
@@ -110,16 +120,6 @@ module ActiveRecord
RGeo::WKRep::WKTParser.new(spatial_factory, support_ewkt: true, default_srid: @srid)
end
end
-
- def factory_attrs
- {
- geo_type: @geo_type.underscore,
- has_m: @has_m,
- has_z: @has_z,
- srid: @srid,
- sql_type: type.to_s
- }
- end
end
end
end
diff --git a/lib/active_record/connection_adapters/postgis/quoting.rb b/lib/active_record/connection_adapters/postgis/quoting.rb
index 1d7c8b9..87b1d5c 100644
--- a/lib/active_record/connection_adapters/postgis/quoting.rb
+++ b/lib/active_record/connection_adapters/postgis/quoting.rb
@@ -12,6 +12,21 @@ module ActiveRecord
super
end
end
+
+ # NOTE: This method should be private in future rails versions.
+ # Hence we should also make it private then.
+ #
+ # See https://github.com/rails/rails/blob/v8.1.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L190
+ def lookup_cast_type(sql_type)
+ type_map.lookup(
+ # oid
+ query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i,
+ # fmod, not needed.
+ nil,
+ # details needed for `..::PostGIS::OID::Spatial` (e.g. `geometry(point,3857)`)
+ sql_type
+ )
+ end
end
end
end
diff --git a/lib/active_record/connection_adapters/postgis/schema_statements.rb b/lib/active_record/connection_adapters/postgis/schema_statements.rb
index f1e02c5..6a02179 100644
--- a/lib/active_record/connection_adapters/postgis/schema_statements.rb
+++ b/lib/active_record/connection_adapters/postgis/schema_statements.rb
@@ -25,7 +25,7 @@ module ActiveRecord
# {:dimension=>2, :has_m=>false, :has_z=>false, :name=>"latlon", :srid=>0, :type=>"GEOMETRY"}
spatial = spatial_column_info(table_name).get(column_name, type_metadata.sql_type)
- SpatialColumn.new(
+ Column.new(
column_name,
get_oid_type(oid.to_i, fmod.to_i, column_name, type),
default_value,
diff --git a/lib/active_record/connection_adapters/postgis_adapter.rb b/lib/active_record/connection_adapters/postgis_adapter.rb
index 1a823e6..1a749e4 100644
--- a/lib/active_record/connection_adapters/postgis_adapter.rb
+++ b/lib/active_record/connection_adapters/postgis_adapter.rb
@@ -12,7 +12,7 @@ require_relative "postgis/schema_statements"
require_relative "postgis/database_statements"
require_relative "postgis/spatial_column_info"
require_relative "postgis/spatial_table_definition"
-require_relative "postgis/spatial_column"
+require_relative "postgis/column"
require_relative "postgis/arel_tosql"
require_relative "postgis/oid/spatial"
require_relative "postgis/oid/date_time"
@@ -84,7 +84,7 @@ module ActiveRecord
# "geometry(Polygon,4326) NOT NULL"
# "geometry(Geography,4326)"
geo_type, srid, has_z, has_m, geographic = PostGIS::OID::Spatial.parse_sql_type(sql_type)
- PostGIS::OID::Spatial.new(geo_type: geo_type, srid: srid, has_z: has_z, has_m: has_m, geographic: geographic)
+ PostGIS::OID::Spatial.new(geo_type: geo_type, srid: srid, has_z: has_z, has_m: has_m, geographic: geographic).freeze
end
end
@@ -92,9 +92,7 @@ module ActiveRecord
end
def native_database_types
- @native_database_types ||= begin
- default_types = PostgreSQLAdapter.native_database_types
- default_types.merge({
+ @native_database_types ||= super.merge({
geography: { name: "geography" },
geometry: { name: "geometry" },
geometry_collection: { name: "geometry_collection" },
@@ -106,7 +104,6 @@ module ActiveRecord
st_point: { name: "st_point" },
st_polygon: { name: "st_polygon" }
})
- end
end
end
|
|
@BuonOmo I could've sworn I enabled that when I opened this... either way either there's no way for me to turn it on if it's off or I can't find the button. If anyone knows where I could find that switch after the PR is opened, let me know. Until then I'll see about applying that patch hopefully soon. |
|
Ok at least for now, that patch has been applied to the branch. |
|
@t27duck TBH it is the first time I push on someone else's PR, and I'm not familiar with it. Would it be ok if I make a new PR using yours? Or same here: if anyone knows how to work this out I'd be glad! otherwise, here's the new patch ^^ commit cd0654b68bbea179c0a3ba317a262147114534e7
Author: Ulysse Buonomo <[email protected]>
Date: Fri Nov 21 21:06:43 2025 +0100
18-master is not yet available
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index fa03d10..b5c97c0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -46,7 +46,7 @@ jobs:
# https://ruby-lang.org/en/downloads/branches
ruby: ["3.4", "3.3", "3.2"]
# https://www.postgresql.org/support/versioning/
- pg: [14-master, 15-master, 16-master, 17-master, 18-master]
+ pg: [14-master, 15-master, 16-master, 17-master, 18-3.6-alpine]
steps:
- name: Set Up Actions
uses: actions/checkout@v4 |
|
@BuonOmo feel free to fork my fork if you want. 👍 |
|
@BuonOmo , you need to fetch their remote and push in this exact branch. You can do it from the Gh or git. |
|
@seuros here is what I did: I also tried to add the StreetIQ repo to my remotes and push there but it was refused (hence my belief that I had not been allowed Any other lead ? Maybe I should have run |
|
I switched the destination branch, you can squash merge, and then open another PR to master from it.. Seem like the maintainer edit it not activated. |
Well this I knew how to do 😅 but I wanted @t27duck to keep edit rights as well :/ |
|
I'm fine with whatever. My app can coast on this branch if being able to do your own thing is easier. |
|
Hehe i know. It just i tested myself too, i can't push . @t27duck need to check the checkbox in bellow the participants...
|
|
I made a new PR, please review it, I'll ship soon if nothing is blocking! |


cast_typebeing the second parameter forSpatialColumn.initialize.spatial_factorythe object could be frozen for whatever reason.These changes require the changes from rgeo/rgeo-activerecord#83 so that gem is set to pull from the repo in this branch.
At least locally, there are 5 failures and 2 errors in the test suite with these changes. The failures are all in the deprecation tests and the errors are related to connection tests (I think).
I've been running both this branch and the changes to
rgeo-activerecordin an app for several weeks with no issue, though granted the app only really cares about storing and retrieving geometry data with minimal to no querying.If nothing else, here's a good starting point.