2016-11-08 62 views
0

我試圖建立一些Rails的模型上active_resource寶石的頂部工作(的ActiveResource)使用自定義REST集合架構Rails ActiveResource?

module Core 
    class RestResource < ActiveResource::Base 
     self.format = :json 
    end 
end 

module Core 
    module API 
     class BaseModel < ::Core::RestResource 
     self.site = ENV['API_URI'] 
     self.headers['Api-Token'] = ENV['API_TOKEN'] 
     end 
    end 
end 

module Core 
    module API 
     class MyModel < ::Core::API::BaseModel 
     end 
    end 
end 

,我試圖運行軌道控制檯如下

2.3.1 :001 > MyModel = Core::API::MyModel 
=> Core::API::MyModel 
2.3.1 :002 > MyModel.all 
ArgumentError: expected an attributes Hash, got ["data", [{"first_name"=>"walter", "last_name"=>"white", "timestamp"=>1478515925}]] 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1377:in `load' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1124:in `initialize' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1051:in `new' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1051:in `instantiate_record' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1047:in `block in instantiate_collection' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/collection.rb:68:in `block in collect!' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/collection.rb:8:in `each' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/collection.rb:8:in `each' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/collection.rb:68:in `collect!' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1047:in `instantiate_collection' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:1016:in `find_every' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:923:in `find' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/bundler/gems/activeresource-f4bec7f8f389/lib/active_resource/base.rb:949:in `all' 
    from (irb):2 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/gems/railties-5.0.0.1/lib/rails/commands/console.rb:65:in `start' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/gems/railties-5.0.0.1/lib/rails/commands/console_helper.rb:9:in `start' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:78:in `console' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:49:in `run_command!' 
    from /Users/nakwa/.rvm/gems/ruby-2.3.1/gems/railties-5.0.0.1/lib/rails/commands.rb:18:in `<top (required)>' 
    from bin/rails:4:in `require' 
    from bin/rails:4:in `<main>' 
2.3.1 :003 > 

在我的rails控制檯(導軌實例爲API供電)我可以看到

Started GET "/v1/my_model.json" for ::1 at 2016-11-08 16:42:11 +0100 
Processing by V1::MyModelController#index as JSON 
    MyModel Load (0.2ms) SELECT "my_model".* FROM "my_model" 
[active_model_serializers] Rendered V1::MyModelSerializer with MyModelSerializer::Adapter::Attributes (2.2ms) 
Completed 200 OK in 13ms (Views: 2.8ms | ActiveRecord: 1.8ms) 

我的理解是,Rails的activeresource期望JSON API返回氡是這樣的:

[ 
    {"first_name": "walter", "last_name": "white"}, 
    {"first_name": "chuck", "last_name": "norris"} 
] 

當我的收藏是這樣的:

{ 
    "data": [ 
    {"first_name": "walter", "last_name": "white"}, 
    {"first_name": "chuck", "last_name": "norris"} 
    ], 
    "collection": { 
    "total_entries": 2 
    } 
} 

我現在正在尋找定製的ActiveResource集合解析器的一個很好的方式,大概就像Backbone.js的是做(http://backbonejs.org/#Collection-parse ),但不知何故,我無法找出這個問題的明顯答案。

有什麼想法?謝謝!

+0

,你能否告訴我們「/ v1/my_model.json」操作的代碼?也許錯誤是在服務器(API)端,而不是在客戶端(ActiveResource)端。 – Wikiti

+0

這是一個複雜的應用程序,運行多個端點...我在上面的示例中重命名了變量,但大多數情況下,這只是標準控制器中的基本索引方法,呈現active_model_serializers。 API的輸出正是上面的那個。問題出在客戶端,沒有在API服務器上。 – nakwa

回答

1

默認情況下ActiveResource對API返回的數據格式有很強烈的期望,但是您可以針對這種情況提供自己的格式

實現一些預期方法的任何Ruby對象都可以用作格式。 ActiveResource本身將模式實現爲模塊,所以我們將堅持這個約定。

作爲一個懶惰的人,我會重用標準JsonFormat執行,只覆蓋方法decode

module CustomJsonFormat 
    include ActiveResource::Formats::JsonFormat 

    extend self 

    def decode(json) 
    ActiveSupport::JSON.decode(json)['data'] 
    end 
end 

現在我們只是告訴的ActiveResource子類來使用它:

class BaseModel < ActiveResource::Base 
    self.format = CustomJsonFormat 

    # ... set self.site, self.headers etc. 
end