From 93a04d9834db17065e2d94a275ae8f724d9d1a6b Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 7 Jul 2014 11:19:55 +0700 Subject: [PATCH 1/2] handle hash with string keys returned from faraday-http-cache --- lib/her/model/attributes.rb | 1 + lib/her/model/orm.rb | 2 ++ spec/model/orm_spec.rb | 49 +++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/lib/her/model/attributes.rb b/lib/her/model/attributes.rb index ea4e79ce..5bada599 100644 --- a/lib/her/model/attributes.rb +++ b/lib/her/model/attributes.rb @@ -32,6 +32,7 @@ def initialize(attributes={}) # # @private def self.initialize_collection(klass, parsed_data={}) + parsed_data = parsed_data.with_indifferent_access collection_data = klass.extract_array(parsed_data).map do |item_data| if item_data.kind_of?(klass) resource = item_data diff --git a/lib/her/model/orm.rb b/lib/her/model/orm.rb index fa91b2df..b9b3c07e 100644 --- a/lib/her/model/orm.rb +++ b/lib/her/model/orm.rb @@ -41,6 +41,8 @@ def save run_callbacks :save do params = to_params self.class.request(to_params.merge(:_method => method, :_path => request_path)) do |parsed_data, response| + parsed_data = parsed_data.with_indifferent_access + assign_attributes(self.class.parse(parsed_data[:data])) if parsed_data[:data].any? @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] diff --git a/spec/model/orm_spec.rb b/spec/model/orm_spec.rb index 5bf523a9..d8f7f9d3 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 From 9cbe6576e4b3adc8392a835bf4382ec151d1bba1 Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 7 Jul 2014 13:03:51 +0700 Subject: [PATCH 2/2] symbolize keys immediately after return the response from faraday --- lib/her/api.rb | 2 +- lib/her/model/attributes.rb | 2 - lib/her/model/http.rb | 1 + lib/her/model/orm.rb | 2 - spec/model/http_spec.rb | 92 +++++++++++++++++++++++++++++++++++++ spec/model/orm_spec.rb | 4 +- 6 files changed, 96 insertions(+), 7 deletions(-) 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 5bada599..8a73dec7 100644 --- a/lib/her/model/attributes.rb +++ b/lib/her/model/attributes.rb @@ -32,7 +32,6 @@ def initialize(attributes={}) # # @private def self.initialize_collection(klass, parsed_data={}) - parsed_data = parsed_data.with_indifferent_access collection_data = klass.extract_array(parsed_data).map do |item_data| if item_data.kind_of?(klass) resource = item_data @@ -172,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/lib/her/model/orm.rb b/lib/her/model/orm.rb index b9b3c07e..fa91b2df 100644 --- a/lib/her/model/orm.rb +++ b/lib/her/model/orm.rb @@ -41,8 +41,6 @@ def save run_callbacks :save do params = to_params self.class.request(to_params.merge(:_method => method, :_path => request_path)) do |parsed_data, response| - parsed_data = parsed_data.with_indifferent_access - assign_attributes(self.class.parse(parsed_data[:data])) if parsed_data[:data].any? @metadata = parsed_data[:metadata] @response_errors = parsed_data[:errors] 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 d8f7f9d3..4bab3860 100644 --- a/spec/model/orm_spec.rb +++ b/spec/model/orm_spec.rb @@ -170,7 +170,7 @@ def on_complete(env) it "handles metadata on a collection" do @users = User.all - @users.metadata[:total_pages].should == 10 + @users.metadata['total_pages'].should == 10 end it "handles error data on a collection" do @@ -180,7 +180,7 @@ def on_complete(env) it "handles metadata on a resource" do @user = User.create(:name => "George Michael Bluth") - @user.metadata[:foo].should == "bar" + @user.metadata['foo'].should == "bar" end it "handles error data on a resource" do