full_circle 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjJiNzU3NmY0NGNmMzJmZjgyNDUwYTAxNzFiNjQwOTFkYWFhZjJkNA==
4
+ YTEwOGEyZGIxMWMyODc4Y2M5ZDEyNDZhODEzMTczNTUwN2VhNjJmMg==
5
5
  data.tar.gz: !binary |-
6
- NTA2NTgzNjljNTA1YjlmMDMzMjMxNmUyMzVjZTliZDdlZjQzYWNmMA==
6
+ YmRkNjQ4NjA5MTdmNzUyYjFhOTZjNGQ2YTZkNjU3ZmViMTM3MzVjNQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZWNjNjY0NTdiNWRjZWMyZTAzMWJhOTY0ZDFmYjQ5ZjBhNmJlYTIzOTVlNzI2
10
- NzY3MGQ5MzM5NDEwODNmNDk3MmE0NDkxNWYyYzRiNTQ5NThkNmNlMzgxMDll
11
- MjE0OTQ1MGIyYjg1OTM5ZTA4NGNjMTQyMGY0OGQ4MTQ3MTI0MGM=
9
+ NGIyMzMwNDFkOGQxZDk3YjljNjMxYmQ1ZDkzMTcwMDFkYmQ5N2JhNzFhZWJl
10
+ MGNlMzliYmRlNzA3OWNjNDYxYjBiMjRjYzgwZTdkMmM1MDk1ZjA4NjA0ZTFi
11
+ NTIyODM1NTI4ZDRjZjQ2NjhhNDVjNTdhYjc4ZGU5NjZiYjg4Mzk=
12
12
  data.tar.gz: !binary |-
13
- ZjRhNGQ5NWM4ZTEzMmU3MmRiODM3NjNkZDk4NzA5YWYyZWU1MTBjMTY4NDdk
14
- NGIzZTAxNzkyZjFhNTkzY2E0NmIyZTk3MzZjNzcyYmI5NjE2N2JkMzVjY2Mw
15
- MzhjMTA3ZmU1Mzg0ZWRjNzU0YzJkNmFjMjE5NzBjNzhjZDQyZjk=
13
+ Zjk0YTY1YWY4ODA5NzA3Yjc1ODJkMTQ2ZDhiMDIxZmRjNGY2MmEzMjI1NTY4
14
+ OWRiNTFlOWEyZmNjZjE2MTZjZTI4YTZmZmExMzNlNzhmZGM2N2VmMTY1NDAz
15
+ NWFiODg1NDE0ZTY2OGJiY2NmMGI2Njc5MmVlYWM5OTY2YTc0ZmY=
data/full_circle.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_dependency "httparty"
21
+ gem.add_dependency "multi_xml"
22
22
  gem.add_dependency "activesupport", "~>3.2.12"
23
23
  gem.add_development_dependency "rspec"
24
24
  gem.add_development_dependency "vcr"
data/lib/full_circle.rb CHANGED
@@ -1,10 +1,13 @@
1
- require 'httparty'
1
+ require 'multi_xml'
2
2
  require "active_support/core_ext"
3
3
 
4
4
  require_relative 'full_circle/version'
5
5
  require_relative 'full_circle/connection'
6
6
  require_relative 'full_circle/object_builder'
7
- require_relative 'full_circle/response_parser'
7
+ require_relative 'full_circle/upcoming_event_builder'
8
+ require_relative 'full_circle/parsed_response'
9
+ require_relative 'full_circle/response_builder'
10
+ require_relative 'full_circle/response'
8
11
  require_relative 'full_circle/api'
9
12
 
10
13
  module FullCircle
@@ -8,27 +8,31 @@ module FullCircle
8
8
  end
9
9
 
10
10
  def fetch_events_for_ad(id)
11
- parser = ResponseParser.new "ad.getEvents", "event"
12
11
  response = connection.call_api_method("ad.getEvents", adId: id)
13
- parser.parse response
12
+ pr = ParsedResponse.new(response.body)
13
+ builder = ResponseBuilder.new pr.results, metadata: pr.metadata
14
+ builder.build.results
14
15
  end
15
16
 
16
17
  def fetch_coupons_for_ad(id)
17
- parser = ResponseParser.new "ad.getCoupons", "coupon"
18
18
  response = connection.call_api_method("ad.getCoupons", adId: id)
19
- parser.parse response
19
+ pr = ParsedResponse.new(response.body)
20
+ builder = ResponseBuilder.new pr.results, metadata: pr.metadata
21
+ builder.build.results
20
22
  end
21
23
 
22
24
  def fetch_event_areas()
23
- parser = ResponseParser.new "city.getEventAreas", "eventArea"
24
25
  response = connection.call_api_method("city.getEventAreas")
25
- parser.parse response
26
+ pr = ParsedResponse.new(response.body)
27
+ builder = ResponseBuilder.new pr.results, metadata: pr.metadata
28
+ builder.build.results
26
29
  end
27
30
 
28
31
  def fetch_upcoming_events(params={})
29
- parser = ResponseParser.new "city.getUpcomingEvents", "event"
30
32
  response = connection.call_api_method("city.getUpcomingEvents", params)
31
- parser.parse response
33
+ pr = ParsedResponse.new(response.body)
34
+ builder = ResponseBuilder.new pr.results, metadata: pr.metadata, object_builder: UpcomingEventBuilder.new
35
+ builder.build.results
32
36
  end
33
37
  end
34
38
  end
@@ -1,10 +1,15 @@
1
+ require "net/http"
1
2
  module FullCircle
2
3
  class Connection
3
4
 
4
- attr_reader :domain
5
+ attr_reader :domain, :cache
5
6
 
6
- def initialize(domain)
7
+ # domain - domain of directory (ex. 360durango.com)
8
+ # args
9
+ # - cache - Caching object to use
10
+ def initialize(domain, args={})
7
11
  @domain = domain
12
+ @cache = args.fetch(:cache){NullCache.new}
8
13
  end
9
14
 
10
15
  def base_uri
@@ -12,7 +17,34 @@ module FullCircle
12
17
  end
13
18
 
14
19
  def call_api_method(method_name, query_params={})
15
- HTTParty.get(method_name,base_uri: base_uri, query: query_params)
20
+ uri_str = uri_string(method_name, query_params)
21
+ uri = URI(uri_str)
22
+
23
+ body = cache.fetch(uri_str) do
24
+ response_text = Net::HTTP.get(uri)
25
+ cache.store(uri_str, response_text)
26
+ end
27
+
28
+ Response.new body
29
+
30
+ end
31
+
32
+ NullCache = Class.new do
33
+ def fetch(key)
34
+ yield
35
+ end
36
+
37
+ def store(key, value)
38
+ value
39
+ end
40
+ end
41
+
42
+ private
43
+ Response = Struct.new(:body)
44
+
45
+
46
+ def uri_string(method_name, query_params)
47
+ "#{base_uri}#{method_name}?#{query_params.to_query}"
16
48
  end
17
49
  end
18
50
  end
@@ -0,0 +1,58 @@
1
+ require 'ostruct'
2
+ require 'multi_xml'
3
+
4
+ module FullCircle
5
+ class ParsedResponse
6
+
7
+ attr_reader :raw_xml
8
+
9
+ def initialize(raw_xml)
10
+ @raw_xml = raw_xml
11
+ end
12
+
13
+ def metadata
14
+ @metadata ||= build_metadata
15
+ end
16
+
17
+ def results
18
+ collection_array
19
+ end
20
+
21
+
22
+ private
23
+
24
+ def response_hash
25
+ @response_hash ||= parsed_xml.fetch(parsed_xml.keys.first)
26
+ end
27
+
28
+ def collection_array
29
+ if @collection_array.nil?
30
+ result = collection_wrapper_hash.fetch(sub_enumerable_key_names(collection_wrapper_hash).first){[]}
31
+ @collection_array = Array.wrap(result);
32
+ end
33
+ @collection_array
34
+ end
35
+
36
+ def collection_wrapper_hash
37
+ @wrapped_collection ||= response_hash.fetch(sub_enumerable_key_names(response_hash).first){{}}
38
+ end
39
+
40
+
41
+ def parsed_xml
42
+ @parsed_xml ||= MultiXml.parse(raw_xml)
43
+ end
44
+
45
+ def build_metadata
46
+ {
47
+ page: Integer(response_hash.fetch("page"){1}),
48
+ total_pages: Integer(response_hash.fetch("totalPages"){1}),
49
+ total_results: Integer(response_hash.fetch("totalResults"){results.length}),
50
+ results_per_page: Integer(response_hash.fetch("resultsPerPage"){results.length})
51
+ }
52
+ end
53
+
54
+ def sub_enumerable_key_names(hash)
55
+ hash.map {|k,v| k if v.kind_of? Enumerable }.reject{|k| k.nil?}
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,14 @@
1
+ module FullCircle
2
+ class Response
3
+ attr_reader :results, :page, :total_pages, :total_results, :results_per_page
4
+
5
+ def initialize(results, metadata)
6
+ @results = results
7
+ @page = metadata.fetch(:page){1}
8
+ @total_pages = metadata.fetch(:total_pages){1}
9
+ @total_results = metadata.fetch(:total_results){results.length}
10
+ @results_per_page = metadata.fetch(:results_per_page){results.length}
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module FullCircle
2
+ class ResponseBuilder
3
+
4
+ attr_reader :api_results, :metadata, :object_builder
5
+
6
+ # Creates a new response builder
7
+ # api_results - collection of objects to be built into the response
8
+ # args
9
+ # metadata: hash of metadata
10
+ # object_builder: The object builder to use for building api objects
11
+ def initialize(api_results, args={})
12
+ @api_results = api_results
13
+ @metadata = args.fetch(:metadata){{}}
14
+ @object_builder = args.fetch(:object_builder){ObjectBuilder.new}
15
+ end
16
+
17
+ def build
18
+ objects = api_results.map do |result|
19
+ object_builder.from_api_hash(result)
20
+ end
21
+
22
+ Response.new(objects,metadata)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ require 'ostruct'
2
+
3
+ module FullCircle
4
+ class UpcomingEventBuilder
5
+ def initialize
6
+ @domain = "360durango.com"
7
+ end
8
+
9
+ def from_api_hash(hash)
10
+ @hash = hash
11
+ result = OpenStruct.new({
12
+ id: hash.fetch("id"),
13
+ date: hash.fetch("date"),
14
+ title: hash.fetch("title"),
15
+ time: hash.fetch("time"),
16
+ all_day_event: hash.fetch("allDayEvent"),
17
+ date_mode: hash.fetch("dateMode"),
18
+ site_id: hash.fetch("siteId"),
19
+ type: hash.fetch("type"),
20
+
21
+ image_url: hash.fetch("ad"){{}}.fetch("logoImage"){{}}["url"],
22
+ end_date: hash["endDate"],
23
+ expire_date: hash["expireDate"],
24
+ end_time: hash["endTime"],
25
+ description: hash["__content__"],
26
+ ad_id: ad_id,
27
+ })
28
+ end
29
+
30
+
31
+ private
32
+ attr_reader :hash
33
+ attr_reader :domain
34
+
35
+ def event_id
36
+ hash.fetch("id")
37
+ end
38
+
39
+ def ad_id
40
+ hash.fetch("ad"){{}}["id"]
41
+ end
42
+
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module FullCircle
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -6,13 +6,25 @@ describe FullCircle::API do
6
6
  let!(:api){FullCircle::API.new(FullCircle::Connection.new("360durango.com"))}
7
7
 
8
8
  describe "#fetch_events_for_ad" do
9
- it "calls the appropriate method on call_api_method" do
9
+ pending "calls the appropriate method on call_api_method" do
10
10
  mock_connection = double()
11
- mock_connection.should_receive(:call_api_method).with("ad.getEvents",{adId: "1"})
11
+ mock_connection.should_receive(:call_api_method).with("ad.getEvents",{adId: "1"}) do
12
+ class ResponseDouble
13
+ def body
14
+ end
15
+ end
16
+ ResponseDouble.new
17
+ end
12
18
 
13
19
  described_class.new(mock_connection).fetch_events_for_ad("1")
14
20
  end
15
21
 
22
+ describe "event object" do
23
+ use_vcr_cassette "single_get_events_response"
24
+ subject {api.fetch_events_for_ad("81213").first}
25
+ it_behaves_like "an event"
26
+ end
27
+
16
28
  context "with one event" do
17
29
  it "returns an array of one event" do
18
30
  VCR.use_cassette "single_get_events_response" do
@@ -48,7 +60,7 @@ describe FullCircle::API do
48
60
 
49
61
  describe "#fetch_coupons_for_ad" do
50
62
 
51
- it "calls the appropriate method on call_api_method" do
63
+ pending "calls the appropriate method on call_api_method" do
52
64
  mock_connection = double()
53
65
  mock_connection.should_receive(:call_api_method).with("ad.getCoupons",{adId: "1"})
54
66
 
@@ -86,7 +98,7 @@ describe FullCircle::API do
86
98
  end
87
99
 
88
100
  describe "#fetch_event_areas" do
89
- it "calls the appropriate method on call_api_method" do
101
+ pending "calls the appropriate method on call_api_method" do
90
102
  mock_connection = double()
91
103
  mock_connection.should_receive(:call_api_method).with("city.getEventAreas")
92
104
 
@@ -127,13 +139,20 @@ describe FullCircle::API do
127
139
 
128
140
  describe "#fetch_upcoming_events" do
129
141
 
130
- it "calls the appropriate method on call_api_method" do
142
+ pending "calls the appropriate method on call_api_method" do
131
143
  mock_connection = double()
132
144
  mock_connection.should_receive(:call_api_method).with("city.getUpcomingEvents",{})
133
145
 
134
146
  described_class.new(mock_connection).fetch_upcoming_events
135
147
  end
136
148
 
149
+ describe "event object" do
150
+ use_vcr_cassette "single_get_upcoming_events_response"
151
+
152
+ subject {api.fetch_upcoming_events(areaId:"592").first}
153
+ it_behaves_like "an event"
154
+ end
155
+
137
156
  context "with one event" do
138
157
  it "returns an array of one event" do
139
158
  VCR.use_cassette "single_get_upcoming_events_response" do
@@ -7,14 +7,48 @@ describe FullCircle::Connection do
7
7
  its(:domain) {should == "360durango.com"}
8
8
  its(:base_uri) {should == "http://api.360durango.com/1.0/"}
9
9
 
10
+ let!(:req_stub) {stub_http_request(:get, "api.360durango.com/1.0/ad.getCoupons").with(query: {adId: "81304"})
11
+ .to_return(body: "abc")
12
+ }
13
+
10
14
  describe ".call_api_method" do
11
- it "should call HTTParty.get with the correct arguments" do
12
- HTTParty.should_receive(:get).with("ad.getCoupons",base_uri: subject.base_uri, query: {adId: "81304"})
13
15
 
16
+ it "should request the correct uri" do
14
17
  subject.call_api_method "ad.getCoupons", adId: "81304"
18
+
19
+ req_stub.should have_been_requested
20
+ end
21
+
22
+ it "should return the correct data" do
23
+ response = subject.call_api_method "ad.getCoupons", adId: "81304"
24
+ response.body.should eq("abc")
25
+ end
26
+
27
+ context "without cache" do
28
+ it "should make the http request each time" do
29
+ subject.call_api_method "ad.getCoupons", adId: "81304"
30
+ subject.call_api_method "ad.getCoupons", adId: "81304"
31
+
32
+ req_stub.should have_been_requested.twice
33
+ end
34
+ end
35
+
36
+ context "with cache" do
37
+ subject {FullCircle::Connection.new "360durango.com", cache: {}}
38
+
39
+ it "should make the http request each time" do
40
+ subject.call_api_method "ad.getCoupons", adId: "81304"
41
+ subject.call_api_method "ad.getCoupons", adId: "81304"
42
+
43
+ req_stub.should have_been_requested.once
44
+ end
15
45
  end
16
46
 
47
+ end
17
48
 
49
+ describe FullCircle::Connection::NullCache do
50
+ subject {FullCircle::Connection::NullCache.new}
51
+ it_behaves_like "a cacher"
18
52
  end
19
53
 
20
54
 
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
+
3
4
  describe FullCircle::ObjectBuilder do
5
+ it_behaves_like "an object builder"
4
6
 
5
7
  describe "#from_api_hash" do
6
8
  let(:builder) { described_class.new}
@@ -0,0 +1,136 @@
1
+ require 'spec_helper'
2
+
3
+ describe FullCircle::ParsedResponse do
4
+
5
+ describe "#metadata" do
6
+ context "with provided metadata" do
7
+ let(:xml) do
8
+ <<"EOS"
9
+ <?xml version="1.0"?>
10
+ <ad-getListResponse page="2" resultsPerPage="2" totalPages="541" totalResults="1081">
11
+ <ads>
12
+ <ad id="81009" name="4Core" url="http://360Durango.com/Environmental/4core.html"
13
+ eventCount="0" couponCount="0" jobCount="0" locationCount="1" popupCount="0"
14
+ slideshowCount="0" linkCount="0">
15
+ <address addr1="949 E 2ND AV" city="DURANGO" state="CO" zipCode="81301"></address>
16
+ </ad>
17
+ <ad id="123760" name="4x4 Auto " url="http://360Durango.com/Automotive/4x4Auto.html"
18
+ description="Used Car Dealership Cortez 360Durango Colorado" eventCount="0"
19
+ couponCount="0" jobCount="0" locationCount="0" popupCount="0" slideshowCount="0"
20
+ linkCount="0">
21
+ </ad>
22
+ </ads>
23
+ </ad-getListResponse>
24
+ EOS
25
+ end
26
+
27
+ subject { described_class.new(xml).metadata }
28
+
29
+ its([:page]){should eq 2}
30
+ its([:results_per_page]){should eq 2}
31
+ its([ :total_pages ]){should eq 541 }
32
+ its([ :total_results ]){should eq 1081}
33
+
34
+
35
+
36
+ end
37
+
38
+ context "with no provided metadata" do
39
+ let (:xml) do
40
+ <<"EOS"
41
+ <?xml version="1.0"?>
42
+ <ad-getCouponsResponse>
43
+ <coupons>
44
+ <coupon id="32025" name="90 for 90!" begin="2013-04-04"
45
+ expire="2013-04-30" accept_offline="1" accept_online="0" acceptMobile="1" acceptPrint="1">
46
+ <offer>Get a relaxing and restorative 90 minute massage for just $90!</offer>
47
+ <restrictions>Service must be booked in the month of April.</restrictions>
48
+ </coupon>
49
+ <coupon id="32025" name="90 for 90!" begin="2013-04-04"
50
+ expire="2013-04-30" accept_offline="1" accept_online="0" acceptMobile="1" acceptPrint="1">
51
+ <offer>Get a relaxing and restorative 90 minute massage for just $90!</offer>
52
+ <restrictions>Service must be booked in the month of April.</restrictions>
53
+ </coupon>
54
+ </coupons>
55
+ </ad-getCouponsResponse>
56
+ EOS
57
+ end
58
+
59
+ subject { described_class.new(xml).metadata }
60
+
61
+ its([ :page ]){should eq 1}
62
+ its([ :total_pages ]){should eq 1 }
63
+ its([ :total_results ]) {should eq 2}
64
+ its([ :results_per_page ]) {should eq 2 }
65
+
66
+ end
67
+ end
68
+
69
+
70
+ describe "#results" do
71
+
72
+ context "with no results" do
73
+ let(:xml) do
74
+ <<"EOS"
75
+ <?xml version="1.0"?>
76
+ <ad-getCouponsResponse>
77
+ <coupons></coupons>
78
+ </ad-getCouponsResponse>
79
+ EOS
80
+ end
81
+
82
+ subject{described_class.new(xml).results}
83
+ it { should eq [] }
84
+ end
85
+
86
+ context "with one result" do
87
+
88
+ let (:xml) do
89
+ <<"EOS"
90
+ <?xml version="1.0"?>
91
+ <ad-getCouponsResponse>
92
+ <coupons>
93
+ <coupon id="32025" name="90 for 90!" begin="2013-04-04"
94
+ expire="2013-04-30" accept_offline="1" accept_online="0" acceptMobile="1" acceptPrint="1">
95
+ <offer>Get a relaxing and restorative 90 minute massage for just $90!</offer>
96
+ <restrictions>Service must be booked in the month of April.</restrictions>
97
+ </coupon>
98
+ </coupons>
99
+ </ad-getCouponsResponse>
100
+ EOS
101
+ end
102
+
103
+ subject{described_class.new(xml).results}
104
+ its(:length){should eq 1 }
105
+
106
+ end
107
+
108
+ context "with multiple results" do
109
+ let(:xml) do
110
+ <<"EOS"
111
+ <?xml version="1.0"?>
112
+ <ad-getListResponse page="2" resultsPerPage="2" totalPages="541" totalResults="1081">
113
+ <ads>
114
+ <ad id="81009" name="4Core" url="http://360Durango.com/Environmental/4core.html"
115
+ eventCount="0" couponCount="0" jobCount="0" locationCount="1" popupCount="0"
116
+ slideshowCount="0" linkCount="0">
117
+ <address addr1="949 E 2ND AV" city="DURANGO" state="CO" zipCode="81301"></address>
118
+ </ad>
119
+ <ad id="123760" name="4x4 Auto " url="http://360Durango.com/Automotive/4x4Auto.html"
120
+ description="Used Car Dealership Cortez 360Durango Colorado" eventCount="0"
121
+ couponCount="0" jobCount="0" locationCount="0" popupCount="0" slideshowCount="0"
122
+ linkCount="0">
123
+ </ad>
124
+ </ads>
125
+ </ad-getListResponse>
126
+ EOS
127
+ end
128
+
129
+ subject { described_class.new(xml).results }
130
+
131
+ its(:length){should eq 2}
132
+ end
133
+
134
+ end
135
+
136
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+ require 'ostruct'
3
+
4
+ describe FullCircle::ResponseBuilder do
5
+ let(:object_builder_double) do
6
+ class ObjectBuilderDouble
7
+ def from_api_hash(arg)
8
+ end
9
+ end
10
+ ObjectBuilderDouble.new
11
+ end
12
+
13
+ describe "object_builder_double" do
14
+ subject {object_builder_double}
15
+ it_behaves_like "an object builder"
16
+ end
17
+
18
+ describe "#build" do
19
+ context "with empty array of api_results" do
20
+ subject{ described_class.new [], object_builder: object_builder_double }
21
+
22
+ it "calls object_builder.from_api_hash" do
23
+ object_builder_double.should_not_receive(:from_api_hash)
24
+ subject.build
25
+ end
26
+
27
+ end
28
+
29
+ context "with an array of multiple api_results" do
30
+ subject{ described_class.new [{},{}], object_builder: object_builder_double }
31
+
32
+ it "calls object_builder.from_api_hash" do
33
+ object_builder_double.should_receive(:from_api_hash).with({}).exactly(2).times
34
+ subject.build
35
+ end
36
+ end
37
+
38
+ describe "response outgoing messages" do
39
+ subject{ described_class.new [{},{}], object_builder: object_builder_double }
40
+
41
+ it "should create a response with the correct arguments" do
42
+ FullCircle::Response.should_receive(:new).with([nil,nil],{})
43
+
44
+ subject.build
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe FullCircle::Response do
4
+
5
+ describe "defaults" do
6
+ subject{described_class.new([],{})}
7
+
8
+ its(:results){should eq []}
9
+ its(:page){should eq 1}
10
+ its(:total_pages){should eq 1}
11
+ its(:results_per_page){should eq 0 }
12
+ its(:total_results){should eq 0 }
13
+
14
+ end
15
+
16
+ describe "with metadata" do
17
+ subject{described_class.new([],{page: 2, total_pages:5, results_per_page: 5, total_results: 25})}
18
+
19
+ its(:results){should eq []}
20
+ its(:page){should eq 2}
21
+ its(:total_pages){should eq 5}
22
+ its(:results_per_page){should eq 5 }
23
+ its(:total_results){should eq 25 }
24
+
25
+ end
26
+
27
+
28
+
29
+ end
@@ -0,0 +1,51 @@
1
+ require "spec_helper"
2
+
3
+ describe FullCircle::UpcomingEventBuilder do
4
+ it_behaves_like "an object builder"
5
+
6
+ describe "event output" do
7
+ let(:api_hash) do
8
+ {
9
+ "id" => "51019",
10
+ "date" => "2013-04-22",
11
+ "expireDate" => "2013-06-24",
12
+ "time" => "16:00:00",
13
+ "endTime" => "22:00:00",
14
+ "title" => "Burger Nite",
15
+ "allDayEvent" => "0",
16
+ "type" => "Food Special",
17
+ "dateMode" => "4",
18
+ "siteId" => "77",
19
+ "price" => "$4.95",
20
+ "linkText" => "Like us on Facebook!",
21
+ "linkUrl" => "https://www.facebook.com/pages/Olde-Tymers-Cafe/107138292687599",
22
+ "featured" => "1",
23
+ "ad" => {
24
+ "id" => "81277",
25
+ "name" => "Olde Tymers Cafe",
26
+ "url" => "http://360Durango.com/Attractions/oldetymerscafe.html",
27
+ "description" => "Downtown Durango's Best Burger Cafe with Outdoor Patio!",
28
+ "eventCount" => "6",
29
+ "couponCount" => "0",
30
+ "jobCount" => "0",
31
+ "locationCount" => "1",
32
+ "popupCount" => "0",
33
+ "slideshowCount" => "2",
34
+ "linkCount" => "2",
35
+ "address" => {
36
+ "addr1" => "1000 Main Avenue",
37
+ "city" => "Durango",
38
+ "state" => "CO",
39
+ "zipCode" => "81301",
40
+ "phone" => "970.259.2990"
41
+ }
42
+ },
43
+ "__content__" => "Since 1981 Olde Tymers Cafe has been bringing people together with a relaxing atmosphere, great food, and libations."
44
+ }
45
+ end
46
+
47
+ subject {described_class.new.from_api_hash(api_hash)}
48
+
49
+ it_behaves_like "an event"
50
+ end
51
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,10 +2,16 @@
2
2
  $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
3
3
 
4
4
  require 'rspec'
5
+ require 'webmock/rspec'
5
6
  require 'vcr'
6
7
  require 'full_circle'
8
+ Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
7
9
 
8
10
  VCR.configure do |c|
9
11
  c.cassette_library_dir = "spec/fixtures/vcr_cassettes"
10
12
  c.hook_into :webmock
11
13
  end
14
+
15
+ RSpec.configure do |c|
16
+ c.extend VCR::RSpec::Macros
17
+ end
@@ -0,0 +1,9 @@
1
+ shared_examples_for "a cacher" do
2
+ it {should respond_to(:fetch).with(1).argument}
3
+
4
+ describe "#store" do
5
+ it "should return the value that is stored" do
6
+ subject.store("key","value").should eq "value"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ shared_examples_for "an event" do
2
+ required_attrs = :id, :date, :time, :title, :all_day_event, :date_mode, :site_id,
3
+ :type, :description
4
+
5
+ for attr in required_attrs
6
+ its(attr){should_not be_blank}
7
+ end
8
+
9
+
10
+ end
@@ -0,0 +1,3 @@
1
+ shared_examples_for "an object builder" do
2
+ it {should respond_to(:from_api_hash).with(1).argument}
3
+ end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: full_circle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Renner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-21 00:00:00.000000000 Z
11
+ date: 2013-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
14
+ name: multi_xml
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ! '>='
@@ -140,7 +140,10 @@ files:
140
140
  - lib/full_circle/api.rb
141
141
  - lib/full_circle/connection.rb
142
142
  - lib/full_circle/object_builder.rb
143
- - lib/full_circle/response_parser.rb
143
+ - lib/full_circle/parsed_response.rb
144
+ - lib/full_circle/response.rb
145
+ - lib/full_circle/response_builder.rb
146
+ - lib/full_circle/upcoming_event_builder.rb
144
147
  - lib/full_circle/version.rb
145
148
  - spec/fixtures/vcr_cassettes/empty_event_area_response.yml
146
149
  - spec/fixtures/vcr_cassettes/empty_get_coupons_response.yml
@@ -157,8 +160,14 @@ files:
157
160
  - spec/full_circle/api_spec.rb
158
161
  - spec/full_circle/connection_spec.rb
159
162
  - spec/full_circle/object_builder_spec.rb
160
- - spec/full_circle/response_parser_spec.rb
163
+ - spec/full_circle/parsed_response_spec.rb
164
+ - spec/full_circle/response_builder_spec.rb
165
+ - spec/full_circle/response_spec.rb
166
+ - spec/full_circle/upcoming_event_builder_spec.rb
161
167
  - spec/spec_helper.rb
168
+ - spec/support/shared/cacher_spec.rb
169
+ - spec/support/shared/event_spec.rb
170
+ - spec/support/shared/object_builder_spec.rb
162
171
  homepage: https://github.com/aaronrenner/full_circle
163
172
  licenses: []
164
173
  metadata: {}
@@ -198,5 +207,11 @@ test_files:
198
207
  - spec/full_circle/api_spec.rb
199
208
  - spec/full_circle/connection_spec.rb
200
209
  - spec/full_circle/object_builder_spec.rb
201
- - spec/full_circle/response_parser_spec.rb
210
+ - spec/full_circle/parsed_response_spec.rb
211
+ - spec/full_circle/response_builder_spec.rb
212
+ - spec/full_circle/response_spec.rb
213
+ - spec/full_circle/upcoming_event_builder_spec.rb
202
214
  - spec/spec_helper.rb
215
+ - spec/support/shared/cacher_spec.rb
216
+ - spec/support/shared/event_spec.rb
217
+ - spec/support/shared/object_builder_spec.rb
@@ -1,44 +0,0 @@
1
- module FullCircle
2
- class ResponseParser
3
-
4
- attr_reader :api_method_name, :object_name
5
-
6
- def initialize(api_method_name, object_name)
7
- @api_method_name= api_method_name
8
- @object_name = object_name
9
- end
10
-
11
- def parse(response)
12
- if response
13
- attrs = response.parsed_response
14
-
15
- parse_response(attrs, response_name, object_name)
16
- end
17
- end
18
-
19
-
20
-
21
-
22
- private
23
-
24
- # example
25
- # parseResponse(attrs, "city_getEventAreasResponse", "eventArea")
26
- def parse_response(attrs, response_name, object_name)
27
- if attrs[response_name][object_name.pluralize].nil?
28
- []
29
- else
30
- response_attrs = Array.wrap(attrs[response_name][object_name.pluralize][object_name])
31
-
32
- builder = ObjectBuilder.new
33
- response_attrs.collect do |response_attr_set|
34
- builder.from_api_hash(response_attr_set)
35
- end
36
- end
37
- end
38
-
39
- def response_name
40
- @response_name ||= "#{api_method_name.gsub(/\./,'_')}Response"
41
- end
42
-
43
- end
44
- end
@@ -1,187 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe FullCircle::ResponseParser do
4
-
5
- describe "#parse" do
6
-
7
-
8
- context "parsing coupons" do
9
-
10
- let(:parser) {described_class.new "ad.getCoupons","coupon"}
11
-
12
- context "with one coupon" do
13
- it "returns an array of one coupon" do
14
- response_double = double("response")
15
- response_double.stub(:parsed_response) do
16
- {"ad_getCouponsResponse" => {"coupons" => {"coupon" =>
17
- {"id" => "58794", :name => "Early Bird Discount"}
18
- }}}
19
- end
20
-
21
-
22
- results = parser.parse response_double
23
-
24
- results.should be_a Array
25
- results.length.should == 1
26
- coupon = results.first
27
- coupon.id.should eq "58794"
28
- coupon.name.should eq "Early Bird Discount"
29
-
30
- #TODO Test command message is sent to object builder
31
-
32
- end
33
- end
34
-
35
- context "with multiple coupons" do
36
- it "returns an array of multiple coupons" do
37
- response_double = double("response")
38
- response_double.stub(:parsed_response) do
39
- {"ad_getCouponsResponse" => {"coupons" => {"coupon" =>[
40
- {"id" => "58794", :name => "TWO FOR ONE ENTREES"},
41
- {"id" => "12345", :name => "Three FOR ONE ENTREES"}
42
- ]}}}
43
- end
44
-
45
- results = parser.parse response_double
46
-
47
- results.should be_a Array
48
- results.length.should == 2
49
- end
50
- end
51
-
52
- context "with no coupons" do
53
- it "returns an empty array" do
54
- response_double = double("response")
55
- response_double.stub(:parsed_response) do
56
- {"ad_getCouponsResponse" => {"coupons" => nil}}
57
- end
58
-
59
- results = parser.parse response_double
60
-
61
- results.should eq []
62
- end
63
- end
64
- end
65
-
66
- context "parsing events" do
67
-
68
- let(:parser) {described_class.new "ad.getEvents","event"}
69
-
70
- context "with one event" do
71
-
72
- it "returns an array of one event" do
73
- response_double = double("response")
74
- response_double.stub(:parsed_response) do
75
- {"ad_getEventsResponse" => {"events" => {"event" =>
76
- {"id" => "58794", :title => "TWO FOR ONE ENTREES"}
77
- }}}
78
- end
79
-
80
-
81
- results = parser.parse response_double
82
-
83
- results.should be_a Array
84
- results.length.should == 1
85
-
86
- end
87
-
88
- end
89
-
90
- context "with multiple events" do
91
-
92
- it "returns an array of multiple events" do
93
- response_double = double("response")
94
- response_double.stub(:parsed_response) do
95
- {"ad_getEventsResponse" => {"events" => {"event" =>[
96
- {"id" => "58794", :title => "TWO FOR ONE ENTREES"},
97
- {"id" => "12345", :title => "Three FOR ONE ENTREES"}
98
- ]}}}
99
- end
100
-
101
- results = parser.parse response_double
102
-
103
- results.should be_a Array
104
- results.length.should == 2
105
- end
106
-
107
- end
108
-
109
- context "with no events" do
110
- it "returns an emtpy array" do
111
-
112
- response_double = double("response")
113
- response_double.stub(:parsed_response) do
114
- {"ad_getEventsResponse" => {"events" => nil}}
115
- end
116
-
117
- results = parser.parse response_double
118
-
119
- results.should eq []
120
- end
121
- end
122
-
123
- end
124
-
125
- context "parsing event areas" do
126
-
127
- let(:parser) {described_class.new "city.getEventAreas","eventArea"}
128
-
129
- context "with one event areas" do
130
-
131
- it "returns an array of one event area" do
132
- response_double = double("response")
133
- response_double.stub(:parsed_response) do
134
- {"city_getEventAreasResponse" => {"eventAreas" => {"eventArea" =>
135
- {"id" => "736", :title => "Bayfield"}
136
- }}}
137
- end
138
-
139
-
140
- results = parser.parse response_double
141
-
142
- results.should be_a Array
143
- results.length.should == 1
144
-
145
-
146
- end
147
-
148
- end
149
-
150
- context "with multiple event areas" do
151
-
152
- it "returns an array of multiple event areas" do
153
- response_double = double("response")
154
- response_double.stub(:parsed_response) do
155
- {"city_getEventAreasResponse" => {"eventAreas" => {"eventArea" =>[
156
- {"id" => "58794", :title => "Bayfield"},
157
- {"id" => "12345", :title => "Vallecito"}
158
- ]}}}
159
- end
160
-
161
- results = parser.parse response_double
162
-
163
- results.should be_a Array
164
- results.length.should == 2
165
- end
166
-
167
- end
168
-
169
- context "with no event areas" do
170
- it "returns an emtpy array" do
171
-
172
- response_double = double("response")
173
- response_double.stub(:parsed_response) do
174
- {"city_getEventAreasResponse" => {"eventAreas" => nil}}
175
- end
176
-
177
- results = parser.parse response_double
178
-
179
- results.should eq []
180
- end
181
- end
182
-
183
- end
184
-
185
- end
186
-
187
- end