rgeo/rgeo-geojson

How to add properties to a Feature

viktorsmari opened this issue · 4 comments

How can I add more items to a Feature property Hash?
Using merge! does not seem to work

irb(main):001:0> ff = RGeo::GeoJSON.decode(Scenario.find(11).polygon)
=> #<RGeo::GeoJSON::FeatureCollection:0x724c>

irb(main):002:0> ff[0].properties
=> {"myType"=>"base_area"}

irb(main):005:0> ff[0].properties.merge!("k"=>"22")
=> {"myType"=>"base_area", "k"=>"22"}

irb(main):006:0> ff[0].properties
=> {"myType"=>"base_area"}

Which works in a 'normal' Hash

nn = Hash.new
=> {}

irb(main):041:0> nn.merge!("k"=>"22")
=> {"k"=>"22"}

irb(main):042:0> nn
=> {"k"=>"22"}

@viktorsmari currently properties returns a duplicate of the hash so it's not mutable once a feature is created. I'm open to changing this though because it would definitely make it easier to work with. I think in order to do what you want to, you'll have to make a new feature every time you want to modify the properties hash.

@BuonOmo since you're more familiar with the GeoJSON library do you have any thoughts about this?

@keithdoggett I don't see any issue per specification, properties is defined as any json object (https://datatracker.ietf.org/doc/html/rfc7946#section-3.2).

However, I think this was made that way for a reason, we can see comments by Tee and Daniel insisting on the fact that it is a copy. I'm not so sure why..

# This is a GeoJSON wrapper entity that corresponds to the GeoJSON
# "Feature" type. It is an immutable type.
#
# This is the default implementation that is generated by
# RGeo::GeoJSON::EntityFactory. You may replace this implementation
# by writing your own entity factory. Note that an alternate Feature
# implementation need not subclass or even duck-type this class.
# the entity factory mediates all interaction between the GeoJSON
# engine and features.

Basically my opinion is that it would be ok to not return a duplicate because the Feature class is a complete wrapper, not included in the core gem, so by making it mutable we don't risk any more complexity. If you'd like to double check (@keithdoggett @viktorsmari) it would not hurt!

In the mean time @viktorsmari you can just override the properties method, e.g:

class RGeo::GeoJSON::Feature
  def properties
    @properties
  end
end

Thanks @BuonOmo! Would you recommend putting this in an config/initializers/ file? I am working in a Rails project.

@viktorsmari It has been a while since I haven't had an issue with rails' reloading system, so I'd say why not. If you end up with something failing, you can also consider putting that in you lib folder.

The best way to see if it works is to try: puts RGeo::GeoJSON::Feature.instance_method(:properties).source_location * ":" where you use the method and you should see the path you have set