cheddargetter_client 0.0.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.
- data/Gemfile +9 -0
- data/Gemfile.lock +38 -0
- data/LICENSE.txt +20 -0
- data/README.md +38 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/cheddargetter_client.gemspec +70 -0
- data/lib/cheddargetter/client.rb +105 -0
- data/lib/cheddargetter/response.rb +416 -0
- data/lib/cheddargetter_client.rb +7 -0
- data/pkg/cheddargetter_client-0.0.0.gem +0 -0
- data/spec/cheddar_getter_client_spec.rb +285 -0
- data/spec/spec_helper.rb +12 -0
- metadata +175 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
crack (0.3.2)
|
5
|
+
diff-lcs (1.1.3)
|
6
|
+
git (1.2.5)
|
7
|
+
httparty (0.10.0)
|
8
|
+
multi_json (~> 1.0)
|
9
|
+
multi_xml
|
10
|
+
jeweler (1.8.4)
|
11
|
+
bundler (~> 1.0)
|
12
|
+
git (>= 1.2.5)
|
13
|
+
rake
|
14
|
+
rdoc
|
15
|
+
json (1.7.6)
|
16
|
+
multi_json (1.5.0)
|
17
|
+
multi_xml (0.5.2)
|
18
|
+
rake (10.0.3)
|
19
|
+
rdoc (3.12)
|
20
|
+
json (~> 1.4)
|
21
|
+
rspec (2.12.0)
|
22
|
+
rspec-core (~> 2.12.0)
|
23
|
+
rspec-expectations (~> 2.12.0)
|
24
|
+
rspec-mocks (~> 2.12.0)
|
25
|
+
rspec-core (2.12.2)
|
26
|
+
rspec-expectations (2.12.1)
|
27
|
+
diff-lcs (~> 1.1.3)
|
28
|
+
rspec-mocks (2.12.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
bundler
|
35
|
+
crack
|
36
|
+
httparty
|
37
|
+
jeweler
|
38
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Brent Wooden
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
This project borrows highly from cheddargetter_client_ruby.
|
2
|
+
I completely reuse their response object.
|
3
|
+
|
4
|
+
I felt however their implementation of calls to the Cheddargetter api were too static,
|
5
|
+
so I implemented a wrapper using method missing. This way if methods
|
6
|
+
are added to the api, they can be easily accessed. Here are some mappings.
|
7
|
+
There should be a noticable pattern.
|
8
|
+
|
9
|
+
|
10
|
+
- #/customers/get
|
11
|
+
-- cg_client_object.customers_get({:customer_code => 'ABCD'}) (code optional)
|
12
|
+
- #/customers/new
|
13
|
+
-- cg_client_object.customers_new({
|
14
|
+
:customer_code => CustomerCode,
|
15
|
+
:firstName => 'W Pain',
|
16
|
+
:lastName => 'Alemeda',
|
17
|
+
:email => 'w_pain@example.com',
|
18
|
+
:subscription => {:planCode => PlanCodes.last}
|
19
|
+
})
|
20
|
+
|
21
|
+
- #/customers/edit
|
22
|
+
-- cg_client.customers_edit({:customer_code => 'ABCD'}, *valid_customer_attributes_hash*)
|
23
|
+
- #/customers/edit-customer
|
24
|
+
-- cg_client.customers_edit_customer({:customer_code => 'ABCD'}, *valid_customer_attributes_hash*)
|
25
|
+
- #/customers/edit-subscription
|
26
|
+
-- cg_client.customers_edit_subscription({:customer_code => 'ABCD'}, {:subscription => *ValidSubscription*})
|
27
|
+
- #/customers/delete
|
28
|
+
-- cg_client.customers_delete({:customer_code => 'ABCD'})
|
29
|
+
- #/customers/cancel
|
30
|
+
-- cg_client.customers_cancel({:customer_code => 'ABCD'})
|
31
|
+
- #/customers/add-item-quantity
|
32
|
+
-- cg_client.customers_add_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}
|
33
|
+
- #/customers/remove-item-quantity
|
34
|
+
-- cg_client.customers_remove_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}, {:quantity => 5})
|
35
|
+
- #/customers/set-item-quantity
|
36
|
+
cg_client.customers_set_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}, {:quantity => 13}
|
37
|
+
|
38
|
+
See the specs more examples. These are copied from them.
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "cheddargetter_client"
|
18
|
+
gem.homepage = "http://github.com/BrentW/cheddargetter_client"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{A ruby wrapper for the Cheddargetter API}
|
21
|
+
gem.description = %Q{A more flexible solution for accessing the Cheddargetter API}
|
22
|
+
gem.email = "brent.wooden@gmail.com"
|
23
|
+
gem.authors = ["Brent Wooden"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
|
26
|
+
gem.add_dependency "httparty", ">= 0.10.0"
|
27
|
+
gem.add_dependency "crack", ">= 0.3.2"
|
28
|
+
end
|
29
|
+
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "cheddargetter_client"
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brent Wooden"]
|
12
|
+
s.date = "2013-01-25"
|
13
|
+
s.description = "A more flexible solution for accessing the Cheddargetter API"
|
14
|
+
s.email = "brent.wooden@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"Gemfile",
|
21
|
+
"Gemfile.lock",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"cheddargetter_client.gemspec",
|
27
|
+
"lib/cheddargetter/client.rb",
|
28
|
+
"lib/cheddargetter/response.rb",
|
29
|
+
"lib/cheddargetter_client.rb",
|
30
|
+
"pkg/cheddargetter_client-0.0.0.gem",
|
31
|
+
"spec/cheddar_getter_client_spec.rb",
|
32
|
+
"spec/spec_helper.rb"
|
33
|
+
]
|
34
|
+
s.homepage = "http://github.com/BrentW/cheddargetter_client"
|
35
|
+
s.licenses = ["MIT"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = "1.8.24"
|
38
|
+
s.summary = "A ruby wrapper for the Cheddargetter API"
|
39
|
+
|
40
|
+
if s.respond_to? :specification_version then
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
45
|
+
s.add_runtime_dependency(%q<crack>, [">= 0"])
|
46
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
48
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
49
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0.10.0"])
|
50
|
+
s.add_runtime_dependency(%q<crack>, [">= 0.3.2"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
53
|
+
s.add_dependency(%q<crack>, [">= 0"])
|
54
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
55
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
56
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
57
|
+
s.add_dependency(%q<httparty>, [">= 0.10.0"])
|
58
|
+
s.add_dependency(%q<crack>, [">= 0.3.2"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
62
|
+
s.add_dependency(%q<crack>, [">= 0"])
|
63
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
64
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
65
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
66
|
+
s.add_dependency(%q<httparty>, [">= 0.10.0"])
|
67
|
+
s.add_dependency(%q<crack>, [">= 0.3.2"])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Cheddargetter
|
2
|
+
class Client
|
3
|
+
include HTTParty
|
4
|
+
base_uri 'https://cheddargetter.com/xml'
|
5
|
+
|
6
|
+
attr_accessor :username, :password, :product_code, :options_mode
|
7
|
+
|
8
|
+
OptionModes = [:customer, :data, :customer_and_data, :no_options]
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
self.username = options[:username] || options["username"]
|
12
|
+
self.password = options[:password] || options["password"]
|
13
|
+
self.product_code = options[:product_code] || options["product_code"]
|
14
|
+
|
15
|
+
raise(ArgumentError, "No username specified") unless username
|
16
|
+
raise(ArgumentError, "No password specified") unless password
|
17
|
+
raise(ArgumentError, "No product_code specified") unless product_code
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(method, *args, &block)
|
21
|
+
parts = method.to_s.split('_')
|
22
|
+
response = post('/' + [parts.slice!(0, 2).join('/'), parts].flatten.join('-'), args)
|
23
|
+
|
24
|
+
if response.parsed_response["error"] && response.parsed_response["error"]["__content__"] && response.parsed_response["error"]["__content__"] == 'Resource not found'
|
25
|
+
raise NoMethodError.new(method.to_s)
|
26
|
+
else
|
27
|
+
::Cheddargetter::Response.new(response)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def post(url, options)
|
32
|
+
set_options_mode(options)
|
33
|
+
|
34
|
+
response = self.class.post(
|
35
|
+
full_url(url, options),
|
36
|
+
:body => filter_customer_code_key(options),
|
37
|
+
:basic_auth => {:username => username, :password => password}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def customers_delete_all
|
42
|
+
#whacky url
|
43
|
+
response = self.class.post(
|
44
|
+
"https://cheddargetter.com/xml/customers/delete-all/confirm/#{Time.now.to_i}/productCode/#{product_code}",
|
45
|
+
:basic_auth => {:username => username, :password => password}
|
46
|
+
)
|
47
|
+
::Cheddargetter::Response.new(response)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def full_url(url, options = [])
|
53
|
+
return_url = url_with_product(url)
|
54
|
+
|
55
|
+
(options.first || {}).each do |name, value|
|
56
|
+
return_url += param_from_attribute_name(name, value) || ''
|
57
|
+
end unless options_mode == :data
|
58
|
+
return_url
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_options_mode(options)
|
62
|
+
if !options || options.length == 0
|
63
|
+
self.options_mode = :no_options
|
64
|
+
elsif options.is_a?(Array) && options.size == 2
|
65
|
+
self.options_mode = :customer_and_data
|
66
|
+
elsif options.first.size == 1
|
67
|
+
self.options_mode = :customer
|
68
|
+
else
|
69
|
+
self.options_mode = :data
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def filter_customer_code_key(array)
|
74
|
+
return {} if !array || array.length == 0
|
75
|
+
hash = (array && array.is_a?(Array) && array.last) || array
|
76
|
+
hash[:code] = hash.delete(:customer_code) if hash[:customer_code]
|
77
|
+
hash
|
78
|
+
end
|
79
|
+
|
80
|
+
def url_with_product(url)
|
81
|
+
url + product_param
|
82
|
+
end
|
83
|
+
|
84
|
+
def product_param
|
85
|
+
"/productCode/#{product_code}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def param_from_attribute_name(name, value)
|
89
|
+
name = 'code' if name.to_sym == :customer_code
|
90
|
+
name_parts = name.to_s.split('_')
|
91
|
+
if name_parts.length > 1
|
92
|
+
name = name.to_s.split('_').map(&:capitalize).join.tap{|str| str.match(/(^\w)/)}.gsub((/^\w/), $1.downcase)
|
93
|
+
end
|
94
|
+
"/#{name}/#{value}" if value
|
95
|
+
end
|
96
|
+
|
97
|
+
def customer_param(customer_code)
|
98
|
+
"/code/#{customer_code}" if customer_code
|
99
|
+
end
|
100
|
+
|
101
|
+
def item_param(item_code)
|
102
|
+
"/itemCode/#{item_code}" if item_code
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,416 @@
|
|
1
|
+
module Cheddargetter
|
2
|
+
class Response
|
3
|
+
SPECIAL_ARRAY_KEYS = {
|
4
|
+
:plans => :plan,
|
5
|
+
:items => :item,
|
6
|
+
:subscriptions => :subscription,
|
7
|
+
:customers => :customer,
|
8
|
+
:invoices => :invoice,
|
9
|
+
:charges => :charge,
|
10
|
+
:transactions => :transaction,
|
11
|
+
:errors => :error
|
12
|
+
}
|
13
|
+
|
14
|
+
#not charges, because codes aren't unique
|
15
|
+
#not invoices, transactions, subscriptions, or errors because they don't have codes
|
16
|
+
ARRAY_TO_HASH_BY_CODE =
|
17
|
+
[:plans, :items, :customers]
|
18
|
+
|
19
|
+
KEY_TO_DATA_TYPE = {
|
20
|
+
:isActive => :boolean,
|
21
|
+
:isFree => :boolean,
|
22
|
+
:trialDays => :integer,
|
23
|
+
:setupChargeAmount => :float,
|
24
|
+
:recurringChargeAmount => :float,
|
25
|
+
:billingFrequencyQuantity => :integer,
|
26
|
+
:createdDatetime => :datetime,
|
27
|
+
:quantityIncluded => :float,
|
28
|
+
:isPeriodic => :boolean,
|
29
|
+
:overageAmount => :float,
|
30
|
+
:isVatExempt => :boolean,
|
31
|
+
:firstContactDatetime => :datetime,
|
32
|
+
:modifiedDatetime => :datetime,
|
33
|
+
:canceledDatetime => :datetime,
|
34
|
+
:ccExpirationDate => :date,
|
35
|
+
:quantity => :float,
|
36
|
+
:billingDatetime => :datetime,
|
37
|
+
:eachAmount => :float,
|
38
|
+
:number => :integer,
|
39
|
+
:amount => :float,
|
40
|
+
:transactedDatetime => :datetime,
|
41
|
+
:vatRate => :float
|
42
|
+
}
|
43
|
+
|
44
|
+
attr_accessor :raw_response, :clean_response
|
45
|
+
|
46
|
+
def initialize(response) #:nodoc:
|
47
|
+
self.raw_response = response
|
48
|
+
create_clean_response
|
49
|
+
end
|
50
|
+
|
51
|
+
[:errors, :plans, :customers].each do |key|
|
52
|
+
define_method key.to_s do
|
53
|
+
self[key]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#true if the response from CheddarGetter was valid
|
58
|
+
def valid?
|
59
|
+
self.errors.size == 0 && self.raw_response.code < 400
|
60
|
+
end
|
61
|
+
|
62
|
+
#the error messages (if there were any) if the CheddarGetter response was invalid
|
63
|
+
def error_messages
|
64
|
+
self.errors.map do |e|
|
65
|
+
msg = nil
|
66
|
+
if e
|
67
|
+
msg = e[:text]
|
68
|
+
msg += ": #{e[:fieldName]}" unless e[:fieldName].blank?
|
69
|
+
end
|
70
|
+
msg
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#Returns the given plan.
|
75
|
+
#
|
76
|
+
#code must be provided if this response contains more than one plan.
|
77
|
+
def plan(code = nil)
|
78
|
+
retrieve_item(self, :plans, code)
|
79
|
+
end
|
80
|
+
|
81
|
+
#Returns the items for the given plan.
|
82
|
+
#
|
83
|
+
#code must be provided if this response contains more than one plan.
|
84
|
+
def plan_items(code = nil)
|
85
|
+
(plan(code) || { })[:items]
|
86
|
+
end
|
87
|
+
|
88
|
+
#Returns the given item for the given plan.
|
89
|
+
#
|
90
|
+
#item_code must be provided if the plan has more than one item.
|
91
|
+
#
|
92
|
+
#code must be provided if this response contains more than one plan.
|
93
|
+
def plan_item(item_code = nil, code = nil)
|
94
|
+
retrieve_item(plan(code), :items, item_code)
|
95
|
+
end
|
96
|
+
|
97
|
+
#Returns the given customer.
|
98
|
+
#
|
99
|
+
#code must be provided if this response contains more than one customer.
|
100
|
+
def customer(code = nil)
|
101
|
+
retrieve_item(self, :customers, code)
|
102
|
+
end
|
103
|
+
|
104
|
+
#Returns the current subscription for the given customer.
|
105
|
+
#
|
106
|
+
#code must be provided if this response contains more than one customer.
|
107
|
+
def customer_subscription(code = nil)
|
108
|
+
#current subscription is always the first one
|
109
|
+
(customer_subscriptions(code) || []).first
|
110
|
+
end
|
111
|
+
|
112
|
+
def customer_paypal_preapproval_url(code = nil)
|
113
|
+
customer_subscription[:redirectUrl] || ""
|
114
|
+
end
|
115
|
+
|
116
|
+
#Returns all the subscriptions for the given customer.
|
117
|
+
#Only the first one is active, the rest is historical.
|
118
|
+
#
|
119
|
+
#code must be provided if this response contains more than one customer.
|
120
|
+
def customer_subscriptions(code = nil)
|
121
|
+
(customer(code) || { })[:subscriptions]
|
122
|
+
end
|
123
|
+
|
124
|
+
#Returns the current plan for the given customer
|
125
|
+
#
|
126
|
+
#code must be provided if this response contains more than one customer.
|
127
|
+
def customer_plan(code = nil)
|
128
|
+
(customer_subscription(code) || { })[:plan]
|
129
|
+
end
|
130
|
+
|
131
|
+
#Returns the current open invoice for the given customer.
|
132
|
+
#
|
133
|
+
#code must be provided if this response contains more than one customer.
|
134
|
+
def customer_invoice(code = nil)
|
135
|
+
#current invoice is always the first one
|
136
|
+
((customer_subscription(code) || { })[:invoices] || []).first
|
137
|
+
end
|
138
|
+
|
139
|
+
#Returns all of the invoices for the given customer.
|
140
|
+
#
|
141
|
+
#code must be provided if this response contains more than one customer.
|
142
|
+
def customer_invoices(code = nil)
|
143
|
+
(customer_subscriptions(code) || []).map{ |s| s[:invoices] || [] }.flatten
|
144
|
+
end
|
145
|
+
|
146
|
+
#Returns the last billed invoice for the given customer.
|
147
|
+
#This is not the same as the currect active invoice.
|
148
|
+
#
|
149
|
+
#nil if there is no last billed invoice.
|
150
|
+
#
|
151
|
+
#code must be provided if this response contains more than one customer.
|
152
|
+
def customer_last_billed_invoice(code = nil)
|
153
|
+
#last billed invoice is always the second one
|
154
|
+
(customer_invoices(code) || [])[1]
|
155
|
+
end
|
156
|
+
|
157
|
+
#Returns all of the transactions for the given customer.
|
158
|
+
#
|
159
|
+
#code must be provided if this response contains more than one customer.
|
160
|
+
def customer_transactions(code = nil)
|
161
|
+
customer_invoices(code).map{ |s| s[:transactions] || [] }.flatten
|
162
|
+
end
|
163
|
+
|
164
|
+
def customer_one_time_invoices(code = nil)
|
165
|
+
customer_invoices(code).select{ |s| s[:type] == 'one-time' }
|
166
|
+
end
|
167
|
+
#Returns the last transaction for the given customer.
|
168
|
+
#
|
169
|
+
#nil if there are no transactions.
|
170
|
+
#
|
171
|
+
#code must be provided if this response contains more than one customer.
|
172
|
+
def customer_last_transaction(code = nil)
|
173
|
+
invoice = customer_last_billed_invoice(code) || { }
|
174
|
+
(invoice[:transactions] || []).first
|
175
|
+
end
|
176
|
+
|
177
|
+
#Returns an array of any currently outstanding invoices for the given customer.
|
178
|
+
#
|
179
|
+
#code must be provided if this response contains more than one customer.
|
180
|
+
def customer_outstanding_invoices(code = nil)
|
181
|
+
now = Time.now
|
182
|
+
customer_invoices(code).reject do |i|
|
183
|
+
i[:paidTransactionId] || i[:billingDatetime] > now
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
#Info about the given item for the given customer.
|
188
|
+
#Merges the plan item info with the subscription item info.
|
189
|
+
#
|
190
|
+
#item_code must be provided if the customer is on a plan with more than one item.
|
191
|
+
#
|
192
|
+
#code must be provided if this response contains more than one customer.
|
193
|
+
def customer_item(item_code = nil, code = nil)
|
194
|
+
sub_item = retrieve_item(customer_subscription(code), :items, item_code)
|
195
|
+
plan_item = retrieve_item(customer_plan(code), :items, item_code)
|
196
|
+
return nil unless sub_item && plan_item
|
197
|
+
item = plan_item.dup
|
198
|
+
item[:quantity] = sub_item[:quantity]
|
199
|
+
item
|
200
|
+
end
|
201
|
+
|
202
|
+
#The amount remaining for a given item for a given customer.
|
203
|
+
#
|
204
|
+
#item_code must be provided if the customer is on a plan with more than one item.
|
205
|
+
#
|
206
|
+
#code must be provided if this response contains more than one customer.
|
207
|
+
def customer_item_quantity_remaining(item_code = nil, code = nil)
|
208
|
+
item = customer_item(item_code, code)
|
209
|
+
item ? item[:quantityIncluded] - item[:quantity] : 0
|
210
|
+
end
|
211
|
+
|
212
|
+
#The overage amount for the given item for the given customer. 0 if they are still under their limit.
|
213
|
+
#
|
214
|
+
#item_code must be provided if the customer is on a plan with more than one item.
|
215
|
+
#
|
216
|
+
#code must be provided if this response contains more than one customer.
|
217
|
+
def customer_item_quantity_overage(item_code = nil, code = nil)
|
218
|
+
over = -customer_item_quantity_remaining(item_code, code)
|
219
|
+
over = 0 if over <= 0
|
220
|
+
over
|
221
|
+
end
|
222
|
+
|
223
|
+
#The current overage cost for the given item for the given customer.
|
224
|
+
#
|
225
|
+
#item_code must be provided if the customer is on a plan with more than one item.
|
226
|
+
#
|
227
|
+
#code must be provided if this response contains more than one customer.
|
228
|
+
def customer_item_quantity_overage_cost(item_code = nil, code = nil)
|
229
|
+
item = customer_item(item_code, code)
|
230
|
+
return 0 unless item
|
231
|
+
overage = customer_item_quantity_overage(item_code, code)
|
232
|
+
item[:overageAmount] * overage
|
233
|
+
end
|
234
|
+
|
235
|
+
#true if the customer is canceled
|
236
|
+
#
|
237
|
+
#code must be provided if this reponse contains more than one customer
|
238
|
+
def customer_canceled?(code = nil)
|
239
|
+
sub = customer_subscription(code)
|
240
|
+
sub ? !!sub[:canceledDatetime] : nil
|
241
|
+
end
|
242
|
+
|
243
|
+
# Get an array representation of a single customer's current subscription
|
244
|
+
# @throws CheddarGetter_Response_Exception if the response type is incompatible or if a $code
|
245
|
+
# is not provided and the response contains more than one customer
|
246
|
+
# @return array
|
247
|
+
def customer_active?(code = nil)
|
248
|
+
subscription = customer_subscription(code)
|
249
|
+
if subscription[:canceledDatetime] && subscription[:canceledDatetime] <= Time.now
|
250
|
+
false
|
251
|
+
else
|
252
|
+
true
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Is this customer's account pending paypal preapproval confirmation?
|
257
|
+
def customer_waiting_for_paypal?(code = nil)
|
258
|
+
subscription = customer_subscription(code)
|
259
|
+
if subscription[:canceledDatetime] && subscription[:canceledDatetime] <= Time.now && subscription[:cancelType] == 'paypal-wait'
|
260
|
+
true
|
261
|
+
else
|
262
|
+
false
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
#access the root keys of the response directly, such as
|
267
|
+
#:customers, :plans, or :errors
|
268
|
+
def [](value)
|
269
|
+
self.clean_response[value]
|
270
|
+
end
|
271
|
+
|
272
|
+
private
|
273
|
+
def deep_fix_array_keys!(data)
|
274
|
+
if data.is_a?(Array)
|
275
|
+
data.each do |v|
|
276
|
+
deep_fix_array_keys!(v)
|
277
|
+
end
|
278
|
+
elsif data.is_a?(Hash)
|
279
|
+
data.each do |k, v|
|
280
|
+
deep_fix_array_keys!(v)
|
281
|
+
sub_key = SPECIAL_ARRAY_KEYS[k]
|
282
|
+
if sub_key && v.is_a?(Hash) && v.keys.size == 1 && v[sub_key]
|
283
|
+
data[k] = v = [v[sub_key]].flatten
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def deep_symbolize_keys!(data)
|
290
|
+
if data.is_a?(Array)
|
291
|
+
data.each do |v|
|
292
|
+
deep_symbolize_keys!(v)
|
293
|
+
end
|
294
|
+
elsif data.is_a?(Hash)
|
295
|
+
data.keys.each do |key|
|
296
|
+
deep_symbolize_keys!(data[key])
|
297
|
+
data[(key.to_sym rescue key) || key] = data.delete(key)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def deep_fix_data_types!(data)
|
303
|
+
if data.is_a?(Array)
|
304
|
+
data.each do |v|
|
305
|
+
deep_fix_data_types!(v)
|
306
|
+
end
|
307
|
+
elsif data.is_a?(Hash)
|
308
|
+
data.each do |k, v|
|
309
|
+
deep_fix_data_types!(v)
|
310
|
+
type = KEY_TO_DATA_TYPE[k]
|
311
|
+
if type && v.is_a?(String)
|
312
|
+
data[k] = case type
|
313
|
+
when :integer then v.to_i
|
314
|
+
when :float then v.to_f
|
315
|
+
when :datetime then Time.parse(v) rescue v
|
316
|
+
when :date then Date.parse(v) rescue v
|
317
|
+
when :boolean then v.to_i != 0
|
318
|
+
else v
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def make_plan_in_subscription_singular!(data)
|
326
|
+
return unless data[:customers]
|
327
|
+
data[:customers].each do |c|
|
328
|
+
c[:subscriptions].each do |s|
|
329
|
+
if s[:plans].size != 1
|
330
|
+
raise ArgumentError, "Should be exactly one plan in a subscription!"
|
331
|
+
end
|
332
|
+
s[:plan] = s[:plans].first
|
333
|
+
s.delete(:plans)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def switch_arrays_to_hashes!(data)
|
339
|
+
if data.is_a?(Array)
|
340
|
+
data.each do |v|
|
341
|
+
switch_arrays_to_hashes!(v)
|
342
|
+
end
|
343
|
+
elsif data.is_a?(Hash)
|
344
|
+
data.each do |k, v|
|
345
|
+
switch_arrays_to_hashes!(v)
|
346
|
+
if ARRAY_TO_HASH_BY_CODE.include?(k) && v.is_a?(Array)
|
347
|
+
new_hash = { }
|
348
|
+
v.each do |item|
|
349
|
+
new_hash[item[:code]] = item
|
350
|
+
end
|
351
|
+
data[k] = new_hash
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def reduce_clean_errors!(data)
|
358
|
+
root_plural = [(data.delete(:errors) || { })[:error]].flatten
|
359
|
+
root_singular = [data.delete(:error)]
|
360
|
+
embed_singluar = []
|
361
|
+
embed_plural = []
|
362
|
+
|
363
|
+
embed = data[:customers] || data[:plans]
|
364
|
+
if embed
|
365
|
+
embed_singluar = [(embed.delete(:errors) || { })[:error]].flatten
|
366
|
+
embed_plural = [embed.delete(:error)]
|
367
|
+
end
|
368
|
+
|
369
|
+
new_errors = (root_plural + root_singular + embed_plural + embed_singluar).compact
|
370
|
+
|
371
|
+
new_errors.each do |e|
|
372
|
+
aux_code = (e[:auxCode] || "")
|
373
|
+
if aux_code[":"]
|
374
|
+
split_aux_code = aux_code.split(':')
|
375
|
+
e[:fieldName] = split_aux_code.first
|
376
|
+
e[:errorType] = split_aux_code.last
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
data[:errors] = new_errors
|
381
|
+
end
|
382
|
+
|
383
|
+
def create_clean_response
|
384
|
+
data = { }
|
385
|
+
|
386
|
+
#if it isn't a hash, then we didn't get anything useful back.
|
387
|
+
if self.raw_response.parsed_response.is_a?(Hash)
|
388
|
+
#because Crack can:t get attributes and text at the same time.
|
389
|
+
#so we fix the error blocks and re-parse
|
390
|
+
data = ::Crack::XML.parse(self.raw_response.body.gsub(/<error(.*)>(.*)<\/error>/,
|
391
|
+
'<error\1><text>\2</text></error>'))
|
392
|
+
end
|
393
|
+
|
394
|
+
deep_symbolize_keys!(data)
|
395
|
+
reduce_clean_errors!(data)
|
396
|
+
deep_fix_array_keys!(data)
|
397
|
+
deep_fix_data_types!(data)
|
398
|
+
make_plan_in_subscription_singular!(data)
|
399
|
+
switch_arrays_to_hashes!(data)
|
400
|
+
self.clean_response = data
|
401
|
+
end
|
402
|
+
|
403
|
+
def retrieve_item(root, type, code = nil)
|
404
|
+
hash = root[type]
|
405
|
+
if !hash
|
406
|
+
raise ArgumentError, "Can:t get #{type} from a response that doesn't contain #{type}"
|
407
|
+
elsif code
|
408
|
+
hash[code.to_s]
|
409
|
+
elsif hash.size <= 1
|
410
|
+
hash.first.last
|
411
|
+
else
|
412
|
+
raise ArgumentError, "This response contains multiple #{type} so you need to provide the code for the one you wish to get"
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
Binary file
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Cheddargetter::Client do
|
3
|
+
before do
|
4
|
+
class Cheddargetter::Response
|
5
|
+
def self.new(response)
|
6
|
+
response
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Username = 'brent.wooden@gmail.com'
|
12
|
+
Password = 'j3rkface'
|
13
|
+
ProductCode = 'BEETLEBOTS'
|
14
|
+
UserCodes = ["T_ROC", "BDOG_RUEZ"]
|
15
|
+
PlanCodes = ["BEETLEBOTS", "SPIDERBOTS"]
|
16
|
+
ValidSubscription = {
|
17
|
+
:planCode => PlanCodes.first,
|
18
|
+
:ccFirstName => 'W Pain',
|
19
|
+
:ccLastName => "Almeda",
|
20
|
+
:ccNumber => '4111111111111111',
|
21
|
+
:ccExpiration => "04/#{(Date.today.year + 2).to_s}"
|
22
|
+
}
|
23
|
+
|
24
|
+
CustomerCode = "W_PAIN"
|
25
|
+
ValidCustomer = {
|
26
|
+
:customer_code => CustomerCode,
|
27
|
+
:firstName => 'W Pain',
|
28
|
+
:lastName => 'Alemeda',
|
29
|
+
:email => 'w_pain@example.com',
|
30
|
+
:subscription => {:planCode => PlanCodes.last}
|
31
|
+
}
|
32
|
+
|
33
|
+
let(:item_code) { "BATTERY" }
|
34
|
+
ChargeCode = 'LATE_FEE'
|
35
|
+
|
36
|
+
def create_customer_with_code(code)
|
37
|
+
valid_customer = {
|
38
|
+
:customer_code => code,
|
39
|
+
:firstName => code.split('_').first.downcase.capitalize,
|
40
|
+
:lastName => code.split('_').last.downcase.capitalize,
|
41
|
+
:email => "#{code.downcase}@example.com",
|
42
|
+
:subscription => {:planCode => PlanCodes.last}
|
43
|
+
}
|
44
|
+
|
45
|
+
cg_client.customers_new(valid_customer)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
describe 'new' do
|
50
|
+
subject { Cheddargetter::Client.new(options) }
|
51
|
+
context 'with no username option' do
|
52
|
+
let(:options) {{ :password => Password, :product_code => ProductCode }}
|
53
|
+
it 'should raise correct arguement error' do
|
54
|
+
begin
|
55
|
+
subject
|
56
|
+
rescue Exception => e
|
57
|
+
e.to_s.include?("username").should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with no password option' do
|
63
|
+
let(:options) {{ :username => Username, :product_code => ProductCode }}
|
64
|
+
it 'should raise correct arguement error' do
|
65
|
+
begin
|
66
|
+
subject
|
67
|
+
rescue Exception => e
|
68
|
+
e.to_s.include?("password").should be_true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with no product code option' do
|
74
|
+
let(:options) {{ :password => Password, :username => Username }}
|
75
|
+
it 'should raise correct arguement error' do
|
76
|
+
begin
|
77
|
+
subject
|
78
|
+
rescue Exception => e
|
79
|
+
e.to_s.include?("product_code").should be_true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'client actions' do
|
85
|
+
let!(:cg_client){
|
86
|
+
Cheddargetter::Client.new(
|
87
|
+
:username => 'brent.wooden@gmail.com',
|
88
|
+
:password => 'j3rkface',
|
89
|
+
:product_code => 'BEETLEBOTS'
|
90
|
+
)
|
91
|
+
}
|
92
|
+
|
93
|
+
context 'errors' do
|
94
|
+
describe 'invalid_method' do
|
95
|
+
context 'when invalid controller' do
|
96
|
+
subject { cg_client.invalid_method }
|
97
|
+
specify { lambda { subject }.should raise_error(NoMethodError) }
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when invalid action' do
|
101
|
+
subject { cg_client.customers_invalid_method }
|
102
|
+
specify { lambda { subject }.should raise_error(NoMethodError) }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'customers_delete_all' do
|
108
|
+
subject { cg_client.customers_delete_all.to_s }
|
109
|
+
it { should include('success') }
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'create/delete' do
|
113
|
+
describe 'customers_new' do
|
114
|
+
subject { cg_client.customers_new(ValidCustomer).to_s }
|
115
|
+
it { should include('Alemeda') }
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'customers_delete' do
|
119
|
+
subject { cg_client.customers_delete(:customer_code => CustomerCode).to_s }
|
120
|
+
it { should include 'success' }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'needing existing customers' do
|
125
|
+
before {
|
126
|
+
UserCodes.each do |code|
|
127
|
+
create_customer_with_code(code)
|
128
|
+
end
|
129
|
+
}
|
130
|
+
|
131
|
+
describe "customers_get" do
|
132
|
+
context "with no arguements get all customers" do
|
133
|
+
subject { cg_client.customers_get.to_s }
|
134
|
+
|
135
|
+
UserCodes.each do |user_code|
|
136
|
+
it { should include user_code }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with specified customer' do
|
141
|
+
subject { cg_client.customers_get(:customer_code => UserCodes.first).to_s }
|
142
|
+
it { should include UserCodes.first }
|
143
|
+
it { should_not include UserCodes.last }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'customers_edit_customer' do
|
148
|
+
def reset_customer
|
149
|
+
cg_client.customers_edit_customer({:customer_code => UserCodes.first},{:company => ''}).to_s
|
150
|
+
end
|
151
|
+
|
152
|
+
before { reset_customer }
|
153
|
+
subject { cg_client.customers_edit_customer({:customer_code => UserCodes.first},{:company => 'sbox'}).to_s }
|
154
|
+
|
155
|
+
it 'should update customer' do
|
156
|
+
should include('sbox')
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should reset customer' do
|
160
|
+
reset_customer.should_not include('sbox')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe 'customer_edit_subscription' do
|
166
|
+
before { cg_client.customers_new(ValidCustomer) }
|
167
|
+
subject { cg_client.customers_edit_subscription({:customer_code => CustomerCode},{:subscription => ValidSubscription}).to_s }
|
168
|
+
|
169
|
+
it 'should update subscription' do
|
170
|
+
should include(PlanCodes.first)
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'customers_delete' do
|
174
|
+
subject { cg_client.customers_delete(:customer_code => CustomerCode).to_s }
|
175
|
+
it { should include 'success' }
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe 'customers_edit' do
|
180
|
+
before { sleep(8) }
|
181
|
+
before { cg_client.customers_new(ValidCustomer) }
|
182
|
+
subject { cg_client.customers_edit({:customer_code => CustomerCode},{:company => 'sbox', :subscription => ValidSubscription}).to_s }
|
183
|
+
|
184
|
+
it 'should update subscription' do
|
185
|
+
should include(PlanCodes.first)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should update customer' do
|
189
|
+
should include('sbox')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'customers_delete' do
|
194
|
+
subject { cg_client.customers_delete(:customer_code => CustomerCode).to_s }
|
195
|
+
it { should include 'success' }
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'items' do
|
199
|
+
before { cg_client.customers_new(ValidCustomer) }
|
200
|
+
|
201
|
+
describe 'customers_add_item_quantity' do
|
202
|
+
context 'with a quantity' do
|
203
|
+
subject { cg_client.customers_add_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}, {:quantity => 37}).to_s }
|
204
|
+
|
205
|
+
it { should include '37' }
|
206
|
+
it { should include item_code }
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe 'set_item_quantity' do
|
211
|
+
subject { cg_client.customers_set_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}, {:quantity => 13}).to_s }
|
212
|
+
|
213
|
+
it { should include item_code }
|
214
|
+
it { should include '13' }
|
215
|
+
end
|
216
|
+
|
217
|
+
describe 'customers_add_item_quantity()' do
|
218
|
+
context 'with no quantity set' do
|
219
|
+
subject { cg_client.customers_add_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}).to_s }
|
220
|
+
|
221
|
+
it { should include item_code }
|
222
|
+
it { should include '14' }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
describe 'remove_item_quantity' do
|
228
|
+
subject { cg_client.customers_remove_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}, {:quantity => 5}).to_s }
|
229
|
+
|
230
|
+
it { should include item_code }
|
231
|
+
it { should include '9' }
|
232
|
+
|
233
|
+
describe 'with no quantity set' do
|
234
|
+
subject { cg_client.customers_remove_item_quantity({:customer_code => CustomerCode, :itemCode => item_code}).to_s }
|
235
|
+
|
236
|
+
it { should include item_code }
|
237
|
+
it { should include '8' }
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe 'customers_delete' do
|
242
|
+
subject { cg_client.customers_delete(:customer_code => CustomerCode).to_s }
|
243
|
+
it { should include 'success' }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe 'customers_add_charge' do
|
248
|
+
before { cg_client.customers_new(ValidCustomer) }
|
249
|
+
subject { cg_client.customers_add_charge({:customer_code => CustomerCode}, {:chargeCode => ChargeCode, :quantity => 1, :eachAmount => 113}).to_s }
|
250
|
+
it { should include ChargeCode }
|
251
|
+
it { should include '113' }
|
252
|
+
|
253
|
+
describe 'customers_delete' do
|
254
|
+
subject { cg_client.customers_delete(:customer_code => CustomerCode).to_s }
|
255
|
+
it { should include 'success' }
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe 'customers_delete_charge' do
|
260
|
+
before {
|
261
|
+
cg_client.customers_new(ValidCustomer)
|
262
|
+
cg_client.customers_add_charge({:customer_code => CustomerCode}, {:chargeCode => ChargeCode, :quantity => 1, :eachAmount => 113}).to_s
|
263
|
+
}
|
264
|
+
|
265
|
+
subject { cg_client.customers_delete_charge({:customer_code => CustomerCode}, {:chargeId => charge_id}) }
|
266
|
+
|
267
|
+
let(:charge_id) {
|
268
|
+
cg_client.customers_get({:customer_code => CustomerCode}).
|
269
|
+
parsed_response["customers"]["customer"]["subscriptions"]["subscription"]["invoices"]["invoice"]["charges"]["charge"].last["id"]
|
270
|
+
}
|
271
|
+
it { should_not include charge_id }
|
272
|
+
end
|
273
|
+
|
274
|
+
describe 'invoices_new' do
|
275
|
+
before { cg_client.customers_new(ValidCustomer) }
|
276
|
+
subject { cg_client.invoices_new(
|
277
|
+
{:customer_code => CustomerCode},
|
278
|
+
{:charges => {"1" => {:chargeCode => ChargeCode, :quantity => 1, :eachAmount => 117}}}
|
279
|
+
).to_s }
|
280
|
+
it { should include ChargeCode }
|
281
|
+
it { should include '117' }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path("lib/cheddargetter_client.rb")
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
# == Mock Framework
|
5
|
+
#
|
6
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
7
|
+
#
|
8
|
+
# config.mock_with :mocha
|
9
|
+
# config.mock_with :flexmock
|
10
|
+
# config.mock_with :rr
|
11
|
+
config.mock_with :rspec
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cheddargetter_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brent Wooden
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: crack
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: jeweler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: httparty
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.10.0
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.10.0
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: crack
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.3.2
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.3.2
|
126
|
+
description: A more flexible solution for accessing the Cheddargetter API
|
127
|
+
email: brent.wooden@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files:
|
131
|
+
- LICENSE.txt
|
132
|
+
- README.md
|
133
|
+
files:
|
134
|
+
- Gemfile
|
135
|
+
- Gemfile.lock
|
136
|
+
- LICENSE.txt
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- VERSION
|
140
|
+
- cheddargetter_client.gemspec
|
141
|
+
- lib/cheddargetter/client.rb
|
142
|
+
- lib/cheddargetter/response.rb
|
143
|
+
- lib/cheddargetter_client.rb
|
144
|
+
- pkg/cheddargetter_client-0.0.0.gem
|
145
|
+
- spec/cheddar_getter_client_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
homepage: http://github.com/BrentW/cheddargetter_client
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
hash: 518553288699319148
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 1.8.24
|
172
|
+
signing_key:
|
173
|
+
specification_version: 3
|
174
|
+
summary: A ruby wrapper for the Cheddargetter API
|
175
|
+
test_files: []
|