Forum: Ruby on Rails Trouble consuming REST from OpenStreetMap - self-closing elements, perhaps?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ea8f58d0c06eeb0519eba6ab2594de79?d=identicon&s=25 warren@media.mit.edu (Guest)
on 2009-03-14 23:20
(Received via mailing list)
I'm consuming openstreetmap.org's REST api:
http://wiki.openstreetmap.org/wiki/OSM_Protocol_Ve...

and I get an error when I try to run the following code in my
ActiveResource model:

  # GET /api/0.5/map?bbox=left,bottom,right,top
  def self.features(left,bottom,right,top)
    find(:first, :from=>"/api/0.5/map?bbox=#{left},#{bottom},#{right},#
{top}")
  end

Yields:

undefined method `collect!' for #<Hash:0x22f2798>
RAILS_ROOT: /Users/jeff/Desktop/whooz-osm/whooz-osm

Application Trace | Framework Trace | Full Trace
lib/active_resource/base.rb:595:in `instantiate_collection'
lib/active_resource/base.rb:559:in `find_every'
lib/active_resource/base.rb:508:in `find'
app/models/openstreetmap.rb:9:in `features'

I thought it was this patch, and perhaps it is, in a sense:
http://dev.rubyonrails.org/ticket/8798 (that's why i'm using my own
copy of base.rb; i used their patch)

But in fact, I think it may be because if you actually go to OSM's
response:

http://api.openstreetmap.org/api/0.5/map?bbox=11.5...

you see that they're using self-closing elements, which aren't ever
used in REST examples, as far as I can tell. That is, they use:

<node foo="bar" />

instead of always:

<node>
  <foo>bar</foo>
</node>

Odd, since OSM is run on Rails anyways... so that gives me a Hash:

{"node"=>[{"lon"=>"11.5411444", "user"=>"lesi", (...)

...in which "node" is the only node element. Looks like it's not
recognizing it as self-closing, and treating the rest of the xml as
part of that element.

In any case, it's the following part of /active_resource/base.rb which
is causing the problem:

        def instantiate_collection(collection, prefix_options = {})
          # collection.collect! { |record| instantiate_record(record,
prefix_options) }
          puts collection.inspect
          if collection.is_a?(Hash) && collection.size == 1
            value = collection.values.first
            if value.is_a?(Array)
              value.collect! { |record| instantiate_record(record,
prefix_options) }
            else
              [ instantiate_record(value, prefix_options) ]
            end
          else
            collection.collect! { |record| instantiate_record(record,
prefix_options) }
          end
        end

And I'm not sure how to patch AR to be able to read self-closing
elements... i think it's in /active_resource/formats/xml_format.rb,
but it's kind of opaque to me. Wonder if you have any thoughts on
this? Are self-closing elements a valid expression of REST xml? Can I
filter/reformat in my AR model, or should I extend whatever XML parser
AR is using... rexml, i'd guess... to appropriately read this?
Ea8f58d0c06eeb0519eba6ab2594de79?d=identicon&s=25 warren@media.mit.edu (Guest)
on 2009-03-17 01:27
(Received via mailing list)
FYI!

My good friend Robert (http://www.robertsosinski.com/) responded with
this excellent overview with which I got things running in about 20
lines of code:

####################################################

Hey Jeff,

You are dipping into one of the most interesting facets of REST, and
that is what constitutes REST in terms of routing is up to heated
debate.  The REST that you are used to using with resource routing is
really just the way that Rails has decided to use.  At the end of the
day, with REST the URL should just determine a resource, how it is
formatted can be a bit dicy.

Although OSM uses Rails, their routes are quite a bit off from normal
Rails resource routes.  This may be for a slew of reasons, one of
which there being quite a few devs who have felt the short comings of
terse http verb driven routes.  Active Resource works pretty well when
consuming from a textbook Rails RESTful API, however starts to become
very constricting once there is a deviation from it.  Also, Active
Resource is honestly still a bit buggy, and I would not count on OSM's
xml to not be mal-formed (my experience is that API's that are not
consumed by the developers themselves are often lacking in maturity).
This combination can make automagic Resource driven models
problematic.  One such example is running a Array#collect! method on a
Hash, which is what Active Resource is doing for you, and thus
yielding an error.

The solution, well is to write your own wrapper.  Thankfully this is
pretty easy.  I have had alot of success working with something called
HTTParty (http://railstips.org/2008/7/29/it-s-an-httparty-an...
is-invited) on github (http://github.com/jnunemaker/httparty).
HTTParty is basically a gem that gives you an easy to use interface to
Ruby's HTTP object that is very API centric.  The cool thing, is that
the API does not expect Rails RESTful routes and you can specify how
routes are interfaced with in a very granular way while HTTParty
handles the parsing of xml/json input and redundant domain interface
issues behind the scenes.
This topic is locked and can not be replied to.