I encountered a very specific issue when trying to convert the geometries read from shapefiles to geojson, and for some reason this failed.
I had some very simple code to inspect the shapefiles and see what I should do with them. In that process I also wanted to convert the geometries to geojson (for test), as that is the actual goal for me.
So my code iterates over a folder of shape-files, and then just does an inspection of the first element. This should give me an idea of what all the files contain. The code looked like this
Dir[File.join(root_folder, '*.shp')].sort.each do |shapefile|
puts shapefile
RGeo::Shapefile::Reader.open(shapefile) do |file|
puts "File contains #{file.num_records} records."
record = file.next
puts "First record geometry WKT : #{record.geometry.as_text}"
puts " coordinates : #{record.geometry.coordinates}"
puts " geometry JSON : #{RGeo::GeoJSON.encode(record.geometry)}"
puts " Attributes : #{record.attributes.inspect}"
puts
end
end
I got the weirdest error when trying to run this code
gems/rgeo-0.6.0/lib/rgeo/geos/zm_feature_methods.rb:305:in `block in each': no block given (yield) (LocalJumpError)
Apparently one of the shjapefiles contained a MultiLinestring
with a z
and m
coordinate. All zero, so whyyyyy ? But still: rgeo
should be able to handle that?
I tracked the code in rgeo and found the following culprit in Rgeo::Geos::ZMMultiLineStringMethods
each.map(&:coordinates)
Ooooops. Now how could i fix this? I am currently working on an ancient version of rails, and thus also rgeo
. I could open an issue to fix it, but still I would not be able to update my own version (mostly because of the activerecord-postgis-adapter
).
But, thankfully, we are using ruby and we can hotfix code (reopen the class and fix the bug!). So I added an initializer in config\initializers\fix_rgeo_bug.rb
with the following code
module RGeo
module Geos
module ZMMultiLineStringMethods # :nodoc:
# overwrite to fix!
def coordinates
puts "COOOORDINATES"
coords = []
each do |gm|
coords << gm.coordinates
end
coords
end
end
end
end
... and now my code is running smoothly!!
So awesome it is possible in ruby to reopen classes. And that rails has a well controlled loading system and an entry-point before execution to place my own initializers. I have used this a few times before, mainly to fix outdated gems without having to update them, or add very specific behaviour. It is the combination of having readable code, open source code, and then re-opening classes to add my own behaviour or fix bugs. I am still thankful/happy every day to be working in ruby on rails :clap: :clap: :clap:
I wonder if there are other programming languages or frameworks where this is possible?
Now open an issue on rgeo to address this bug :)