Active resource complaining about expects an hash
Asked Answered
A

2

6

I am using active resource to get data from an api and display it,
My controller model.rb has

class Thr::Vol::Dom < ActiveResource::Base
  class << self
    def element_path(id, prefix_options = {}, query_options = nil)
      prefix_options, query_options = split_options(prefix_options) if query_options.nil?
      "#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
    end

    def collection_path(prefix_options = {}, query_options = nil)
      prefix_options, query_options = split_options(prefix_options) if query_options.nil?
      "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
    end
  end

  ActiveResource::Base.site = 'http://10.00.0.00:8888/'

  self.format = :json
  self.collection_name= "/vv/test/domains"

  def self.find
    x = superclass.find(:one, :from => '/vv/test/domains/2013-06-25T05:03Z')
    x
  end
end

When i call this Thr::Vol::Dom.find method it returns the following error:

ArgumentError: expected an attributes Hash, 
  got ["0.0.0.0", "1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"]

The api is expected to feed something like this

{"abs.com":["0.0.0.0", "1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"]}

for the call i made.

The API returns the correct hash but i guess active resource is not able to read it properly, it is directly reading the value in the key-value pair of the hash.

I want to fix this "ArgumentError" error , i want to display the contents of the returned hash in the view.

Adsorbate answered 29/6, 2013 at 0:11 Comment(3)
Please let me know if it make sense now?Adsorbate
You haven't asked a question. You made several statements about what's happening - could you please explain what it is that's wrong, or that you need help with? Thanks.Copyedit
ohh i am really sorry about that. Let me update the question again.Adsorbate
C
17

You can change how ActiveResource handle json response with

class YourModel < ActiveResource::Base
  self.format = ::JsonFormatter.new(:collection_name)
end

In lib/json_formatter.rb

class JsonFormatter
  include ActiveResource::Formats::JsonFormat

  attr_reader :collection_name

  def initialize(collection_name)
    @collection_name = collection_name.to_s
  end

  def decode(json)
    remove_root(ActiveSupport::JSON.decode(json))
  end

  private

  def remove_root(data)
    if data.is_a?(Hash) && data[collection_name]
      data[collection_name]
    else
      data
    end
  end
end

If you pass self.format = ::JsonFormatter.new(:categories) it will find and remove categories root element in your json returned by your API.

Concern answered 29/6, 2013 at 11:19 Comment(5)
I use this way but in my model have error uninitialized constant JsonFormatterHexagonal
You need to require it manually or add config.autoload_paths += %W(#{config.root}/lib) in config/application.rbConcern
You welcome, please consider accepting the answer for others that might be in your case ;)Concern
I am not owner this question, but I have up this answer from 0 to 1 :DHexagonal
If I can accept this answer , I will do that hehe :D Thank you very muchHexagonal
Z
0

The API is returning a JSON object, not a Ruby hash. You'll need to convert it into a hash by using Ruby's JSON module:

require 'JSON'

hash = JSON.parse('{"abs.com":["0.0.0.0", "1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"]}')

This will return a hash and then you'll notice that the key/value pair will work as expected:

hash["abs.com"] => ["0.0.0.0", "1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"]
Zootomy answered 29/6, 2013 at 10:22 Comment(1)
Can you plz explain more about it, with my little understanding about rails i thought active resource was already doing that for me.Adsorbate

© 2022 - 2024 — McMap. All rights reserved.