2012-03-10 16 views
0

私は、jsonでfreebase APIを使用するようにActiveResourceをセットアップしています.Json Freebaseが返すことでActiveResourceが爆発する以外は、正常に動作するはずです。ActiveResource freebase jsonリクエストで窒息する

NoMethodError: undefined method `collect!' for #<Hash:0x007fd674831dd0> 

どうすれば問題を修正するためにカスタムjsonパーサーを定義できますか?

class Freebase < ActiveResource::Base 
    self.site = "https://www.googleapis.com/" 
    self.format = :json 

    def self.search(word) 
    self.find(:all, :from => "/freebase/v1/search/", :params => { :query => word }) 
    end 

    #https://www.googleapis.com/freebase/v1/search?query=nirvana 

    #Freebase.get('search', :query => 'nirvana') 

end 

JSONが返される:この問題を発見

、それを克服する方法がまだわからない:Railsの3.2.1

UPDATEを使用して

https://www.googleapis.com/freebase/v1/search?query=nirvana

{"status":"200 OK","result":[{"mid":"/m/05b3c","name":"Nirvana","notable":{"name":"Belief","id":"/religion/belief"},"lang":"en","score":67.540009},{"mid":"/m/0b1zz","name":"Nirvana","notable":{"name":"Musical Artist","id":"/music/artist"},"lang":"en","score":64.311432},{"mid":"/m/092bf5","name":"Buddhism","notable":{"name":"Religion","id":"/religion/religion"},"lang":"en","score":33.647118},{"mid":"/m/02_6qh","name":"Nirvana","notable":{"name":"Film","id":"/film/film"},"lang":"en","score":30.068491},{"mid":"/m/01h89tx","name":"Nirvana","notable":{"name":"Musical Album","id":"/music/album"},"lang":"en","score":27.799274},{"mid":"/m/01rn9fm","name":"Nirvana","notable":{"name":"Musical Group","id":"/music/musical_group"},"lang":"en","score":27.445602},{"mid":"/m/015k7","name":"Gautama Buddha","notable":{"name":"Deity","id":"/religion/deity"},"lang":"en","score":24.129679},{"mid":"/m/01rkx5","name":"Mahayana Mahaparinirvana Sutra","lang":"en","score":22.359026},{"mid":"/m/03d7q7v","name":"Nirvana","lang":"en","score":21.034473},{"mid":"/m/055ym7w","name":"Nirvana bootleg recordings","notable":{"name":"Musical Album","id":"/music/album"},"lang":"en","score":19.241596},{"mid":"/m/0122_j","name":"Nevermind","notable":{"name":"Musical Album","id":"/music/album"},"lang":"en","score":18.366383},{"mid":"/m/04n7mt","name":"Nirvana fallacy","lang":"en","score":17.212397},{"mid":"/m/0484q","name":"Kurt Cobain","notable":{"name":"Musician","id":"/m/09jwl"},"lang":"en","score":16.594929},{"mid":"/m/027_k8j","name":"Nirvana","lang":"en","score":16.336584},{"mid":"/m/0285c","name":"Dave Grohl","notable":{"name":"Musician","id":"/m/09jwl"},"lang":"en","score":16.115103},{"mid":"/m/068shv","name":"Smells Like Nirvana","notable":{"name":"Musical Album","id":"/music/album"},"lang":"en","score":15.350652},{"mid":"/m/01kq85c","name":"Manic Nirvana","notable":{"name":"Musical Album","id":"/music/album"},"lang":"en","score":15.275189},{"mid":"/m/0437sc","name":"Lithium","notable":{"name":"Composition","id":"/music/song"},"lang":"en","score":14.637386},{"mid":"/m/055kh1","name":"Mechanus","lang":"en","score":14.621847},{"mid":"/m/01f1vf","name":"Lucifer","notable":{"name":"Fictional Character","id":"/fictional_universe/fictional_character"},"lang":"en","score":13.504528}],"cursor":20,"cost":11,"hits":3104} 

https://github.com/rails/rails/issues/2318

+0

共有したコードには、収集するコールは含まれていません!あなたのエラーの原因となっています。あなたの問題についてより正確な情報を提供してください。 – Jon

+0

私はこの例のような何かをしようとしています:多分私は何か間違っているのでしょうか? – ere

+0

は次のように関連しています:https://github.com/rails/rails/issues/2318 – ere

答えて

1

問題は、返されたJSONが、ActiveResourceが期待している方法で形成されていないことです。 AResは返されているメタデータのすべてを期待していませんが、応答の部分にあるものだけを期待しています。

明示的には、あなたが戻って取得している:

{"status":"200 OK","result":[{"mid":"/m/05b3c","name":"Nirvana","notable":{"name" ... 

しかし、ARESは望んでいる:

[{"mid":"/m/05b3c","name":"Nirvana","notable":{"name"... 

私が思い付くことができ、最も簡単な(そしておそらく最も汚い)ソリューションは、ActiveResourceを上書きすることですそのようなモデルでは::ベース#1 find_everyプライベートメソッド:

class Freebase < ActiveResource::Base 

    self.site = "https://www.googleapis.com/" 
    self.format = :json 

    def self.search(word) 
    self.find(:all, :from => "/freebase/v1/search/", :params => { :query => word }) 
    end 

    private 

    def self.find_every(options) 
    begin 
     case from = options[:from] 
     when Symbol 
     instantiate_collection(get(from, options[:params])) 
     when String 
     path = "#{from}#{query_string(options[:params])}" 
     instantiate_collection(format.decode(connection.get(path, headers).body['result']) || []) 
     else 
     prefix_options, query_options = split_options(options[:params]) 
     path = collection_path(prefix_options, query_options) 
     instantiate_collection((format.decode(connection.get(path, headers).body['result']) || []), prefix_options) 
     end 
    rescue ActiveResource::ResourceNotFound 
     # Swallowing ResourceNotFound exceptions and return nil - as per 
     # ActiveRecord. 
     nil 
    end 
    end 

end 

私が作った唯一の変更があります.bodyメソッド呼び出しは今や.body['result']です。この追加により、#instantiate_collectionは、ハッシュではなく予期した配列を受け取るようになりました。

最終的には、これによってエラーが解消されるはずですが、この方法で失われるデータの一部が必要になることがあるため、これですべての問題が解決されることはわかりません。あなたがRestClientのようなものを使用でき、それを使ってモデルを構築することができれば、私の提案はActiveResourceを放棄することです。このアプローチのもう一つの理由は、今のセマンティクスが壊れているということです。あなたはFreebasesのコレクションを取り戻していません。 Freebase APIを使用して検索結果を取得しています。

+0

ええ、私は同じ結論に至りました。私はいくつかのActiveResourceの魔法を望んでいたが、十分に空であることがわかった。私が今質問しているのは、返されたハッシュからレールスタイルのメソッドを作る方法です。 – ere

0

私はデレクのアドバイスに従い、ActiveResourceを放棄した...

他の誰のために私はファラデーを使用して終了とFaraday_Middleware

class Freebase 

    def self.search(id) 
    connection = Faraday.new 'https://www.googleapis.com/freebase/v1' do |conn| 

     conn.adapter Faraday.default_adapter 
     conn.use FaradayMiddleware::ParseJson 
     #conn.use Faraday::Response::Mashify 
    end 

    response = connection.get do |req| 
     req.url('search', :query => id, :limit => 10)#, :filter => '(any namespace:/wikipedia/en_id namespace:/authority/imdb/title)')# #:filter => '(any namespace:/wikipedia/en_id namespace:/authority/imdb/title namespace:/authority/netflix/movie)' , :with => 'commons' 
    end 

    end 

使用できる恐らく外のレールスタイルの方法を作るために、モジュールに内蔵され、いくつかの返されたハッシュですが、私はその部分をまだ理解していません。 ActiveResourceは、他のRailsアプリやRESTFULのルートを完全に模倣しているだけで良いようです。