diff --git a/lib/her/api.rb b/lib/her/api.rb index 5064b8ff..e7693383 100644 --- a/lib/her/api.rb +++ b/lib/her/api.rb @@ -103,7 +103,7 @@ def request(opts={}) end end - { :parsed_data => response.env[:body], :response => response } + { :parsed_data => response.env[:body].symbolize_keys, :response => response } end private diff --git a/lib/her/model/attributes.rb b/lib/her/model/attributes.rb index ea4e79ce..8a73dec7 100644 --- a/lib/her/model/attributes.rb +++ b/lib/her/model/attributes.rb @@ -171,7 +171,6 @@ def new_collection(parsed_data) # # @private def new_from_parsed_data(parsed_data) - parsed_data = parsed_data.with_indifferent_access new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:metadata], :_errors => parsed_data[:errors]) end diff --git a/lib/her/model/http.rb b/lib/her/model/http.rb index 09ab84a3..290d9983 100644 --- a/lib/her/model/http.rb +++ b/lib/her/model/http.rb @@ -91,6 +91,7 @@ def #{method}_collection(path, params={}) def #{method}_resource(path, params={}) path = build_request_path_from_string_or_symbol(path, params) send(:"#{method}_raw", path, params) do |parsed_data, response| + new(parse(parsed_data[:data]).merge :_metadata => parsed_data[:metadata], :_errors => parsed_data[:errors]) end end diff --git a/spec/model/http_spec.rb b/spec/model/http_spec.rb index d982505e..6ba821dd 100644 --- a/spec/model/http_spec.rb +++ b/spec/model/http_spec.rb @@ -153,6 +153,98 @@ end end + context "making HTTP requests that returnd string keys hash" do + before do + class MyCustomParser < Faraday::Response::Middleware + def on_complete(env) + json = JSON.parse(env[:body]) + errors = json.delete('errors') || {} + metadata = json.delete('metadata') || [] + env[:body] = { 'data' => json, 'errors' => errors, 'metadata' => metadata } + end + end + + Her::API.setup :url => "https://api.example.com" do |builder| + builder.use MyCustomParser + builder.use Faraday::Request::UrlEncoded + builder.adapter :test do |stub| + stub.get("/users") { |env| [200, {}, [{ :id => 1 }].to_json] } + stub.get("/users/1") { |env| [200, {}, { :id => 1 }.to_json] } + stub.get("/users/popular") do |env| + if env[:params]["page"] == "2" + [200, {}, [{ :id => 3 }, { :id => 4 }].to_json] + else + [200, {}, [{ :id => 1 }, { :id => 2 }].to_json] + end + end + end + end + + spawn_model "Foo::User" + end + + describe :get do + subject { Foo::User.get(:popular) } + its(:length) { should == 2 } + specify { subject.first.id.should == 1 } + end + + describe :get_raw do + context "with a block" do + specify do + Foo::User.get_raw("/users") do |parsed_data, response| + parsed_data[:data].should == [{ 'id' => 1 }] + end + end + end + + context "with a return value" do + subject { Foo::User.get_raw("/users") } + specify { subject[:parsed_data][:data].should == [{ 'id' => 1 }] } + end + end + + describe :get_collection do + context "with a String path" do + subject { Foo::User.get_collection("/users/popular") } + its(:length) { should == 2 } + specify { subject.first.id.should == 1 } + end + + context "with a Symbol" do + subject { Foo::User.get_collection(:popular) } + its(:length) { should == 2 } + specify { subject.first.id.should == 1 } + end + + context "with extra parameters" do + subject { Foo::User.get_collection(:popular, :page => 2) } + its(:length) { should == 2 } + specify { subject.first.id.should == 3 } + end + end + + describe :get_resource do + context "with a String path" do + subject { Foo::User.get_resource("/users/1") } + its(:id) { should == 1 } + end + + context "with a Symbol" do + subject { Foo::User.get_resource(:"1") } + its(:id) { should == 1 } + end + end + + describe :get_raw do + specify do + Foo::User.get_raw(:popular) do |parsed_data, response| + parsed_data[:data].should == [{ 'id' => 1 }, { 'id' => 2 }] + end + end + end + end + context "setting custom HTTP requests" do before do Her::API.setup :url => "https://api.example.com" do |connection| diff --git a/spec/model/orm_spec.rb b/spec/model/orm_spec.rb index 5bf523a9..4bab3860 100644 --- a/spec/model/orm_spec.rb +++ b/spec/model/orm_spec.rb @@ -140,6 +140,55 @@ end end + context "mapping data, metadata and error data when using Faraday-HTTP-Cache" do + before do + class MyCustomParser < Faraday::Response::Middleware + def on_complete(env) + json = JSON.parse(env[:body]) + data = json.delete('data') + errors = json.delete('errors') || {} + metadata = json.delete('metadata') || [] + env[:body] = { 'data' => data, 'errors' => errors, 'metadata' => metadata } + end + end + + api = Her::API.new + + api.setup :url => "https://api.example.com" do |builder| + builder.use Faraday::Request::UrlEncoded + builder.use MyCustomParser + builder.adapter :test do |stub| + stub.get("/users") { |env| [200, {}, { 'data' => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }], 'metadata' => { :total_pages => 10, :next_page => 2 }, 'errors' => ["Oh", "My", "God"] }.to_json] } + stub.post("/users") { |env| [200, {}, { 'data' => { :name => "George Michael Bluth" }, 'metadata' => { :foo => "bar" }, 'errors' => ["Yes", "Sir"] }.to_json] } + end + end + + spawn_model :User do + uses_api api + end + end + + it "handles metadata on a collection" do + @users = User.all + @users.metadata['total_pages'].should == 10 + end + + it "handles error data on a collection" do + @users = User.all + @users.errors.length.should == 3 + end + + it "handles metadata on a resource" do + @user = User.create(:name => "George Michael Bluth") + @user.metadata['foo'].should == "bar" + end + + it "handles error data on a resource" do + @user = User.create(:name => "George Michael Bluth") + @user.response_errors.should == ["Yes", "Sir"] + end + end + context "defining custom getters and setters" do before do api = Her::API.new