Search code examples
ruby-on-railsrubyescapingactiveresource

Escape '@' in names


I use Rails 4.2.0 with ActiveResource to implement a webclient for server API. The problem I've faced is that server resources contains '@' and '@@' in attribute names. So these attributes can't be processed correctly by ActiveResource while creating ARes object. Example: server returns JSON data:

{"@@artist"=>
  {"@id"=>"some_text_id",
   "@name"=>"Carman",
   "@publisher"=>"Carmen radio",
   "@category"=>"Music",
   "@automaticallyGenerated"=>true,
   "@@options"=>{"@public"=>true, "@enabled"=>false},
   "_extended"=>{"@container"=>"Music box", "region"=>"Europe"}}}

The variant to rename attributes before ARes object is created: (remove '@' from name or replace it for another symbol). In that case I need to do back rename attributes before send POST, PUT requests (call resource.save for example) E.g. add '@' or '@@' in the beginning of the names.

Could you suggest more flexible and pretty variant?


Solution

  • I rly dont know what ist your output, but you can use something like this. This is just example.

    input = {
      "@@artist"=>
      {"@id"=>"some_text_id",
      "@name"=>"Carman",
      "@publisher"=>"Carmen radio",
      "@category"=>"Music",
      "@automaticallyGenerated"=>true,
      "@@options"=>{"@public"=>true, "@enabled"=>false},
      "_extended"=>{"@container"=>"Music box", "region"=>"Europe"}
      }
    }
    
    def transcode(hash)
      result = {}
      hash.each do |k, v|
        result[k.gsub(/@*/, "")] = ( Hash === v ? transcode(v) : v )
      end
      result
    end
    
    output = transcode(input)
    
    #{
    #  "artist" => {
    #  "id" => "some_text_id",
    #  "name" => "Carman",
    #  "publisher" => "Carmen radio",
    #  "category" => "Music",
    #  "automaticallyGenerated" => true,
    #  "options" => {
    #  "public" => true,
    #  "enabled" => false
    #  },
    #  "_extended" => {
    #  "container" => "Music box",
    #  "region" => "Europe"
    #  }
    #  }
    #}
    

    BACK

    input = {
      "@@artist"=>
      {"@id"=>"some_text_id",
      "@name"=>"Carman",
      "@publisher"=>"Carmen radio",
      "@category"=>"Music",
      "@automaticallyGenerated"=>true,
      "@@options"=>{"@public"=>true, "@enabled"=>false},
      "_extended"=>{"@container"=>"Music box", "region"=>"Europe"}
      }
    }
    
    def transcode(hash)
      result = {}
      hash.each do |k, v|
        result[k.gsub(/@*/, "")] = ( Hash === v ? transcode(v) : v )
      end
      result
    end
    
    def transcode_back(hash, output)
      result = {}
      hash.each do |k, v|
        value = output[k.gsub(/@*/, "")]
        result[k] = ( Hash === value ? transcode_back(v, value) : value )
      end
      result
    end
    
    output = transcode(input)
    
    # you can modify values
    #output["artist"]["name"] = "CarmanNew"
    
    result = transcode_back(input, output)
    
    output == result # is same ?
    # true