gocardless 1.9.0 → 1.10.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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed8ff8ba2e1109b3ec370bd8c52e2d1f2dc0ae70
4
- data.tar.gz: 4321b58cabecafefbf4a5257ae6ee6e218d49364
3
+ metadata.gz: d3541d1c3a98b1d8812387e1122381ccf061648d
4
+ data.tar.gz: d1280282fed2de29f439389679a27165dbef197e
5
5
  SHA512:
6
- metadata.gz: f8594375ca0b9ea638fedf5d2fc4ef137b81b791e2248307277eb4459e941b1606abd49f53e86a4829acd2fd3f09d72ca5a3fd5dbaadda148784d65df24d6a0e
7
- data.tar.gz: c92b6f3708f2595533dcc368f904fbd83593f8eabf7059b8b9955cfe5bb964792335e584fd129da8b150773f1c0e9a317e70948a374974682ec12c69d23bd214
6
+ metadata.gz: c4238571659011a414b4ec82b8dab479c9f4bc2274ffd9f6de010e28dad76f34356d7a41be4fe49bb3b354d4a3a8818cff35bb21618c30799b9b42a53763fbec
7
+ data.tar.gz: 4fe530f0bf5531541366cae496bcc8d613abca06e638b11f10d36e3aaba00ce0d2ec7246a6b3aa811a0581a8b494dedc7016f9c92737b1195d17c05858084b7e
@@ -1,3 +1,13 @@
1
+ ## 1.10.0 - June 02, 2014
2
+
3
+ - Add alias methods for boolean attributes
4
+ - Update resources with new attributes
5
+ - Remove any nil values before sending params to GC
6
+ - Support charge_customer_at on bill creation
7
+ - Make depedency specifier less strict
8
+ - Add pagination
9
+
10
+
1
11
  ## 1.9.0 - May 23, 2014
2
12
 
3
13
  - Add ability to refund bills
data/README.md CHANGED
@@ -3,10 +3,7 @@
3
3
  The GoCardless Ruby client provides a simple Ruby interface to the GoCardless
4
4
  API.
5
5
 
6
- If you want to use the library as an individual merchant, refer to the
7
- [merchant guide](https://gocardless.com/docs/ruby/merchant_client_guide). If
8
- you want to support multiple merchant accounts, see the
9
- [partner guide](https://gocardless.com/docs/ruby/partner_client_guide).
6
+ API documentation, usage guides, and setup information can be found at [developer.gocardless.com](https://developer.gocardless.com/ruby/).
10
7
 
11
8
  The full API reference is available at on
12
9
  [rubydoc.info](http://rubydoc.info/github/gocardless/gocardless-ruby/master/frames).
@@ -7,7 +7,6 @@ module GoCardless
7
7
  require 'gocardless/pre_authorization'
8
8
  require 'gocardless/user'
9
9
  require 'gocardless/bill'
10
- require 'gocardless/payment'
11
10
  require 'gocardless/merchant'
12
11
  require 'gocardless/client'
13
12
  require 'gocardless/payout'
@@ -5,20 +5,29 @@ module GoCardless
5
5
  creatable
6
6
 
7
7
  attr_accessor :amount,
8
- :source_type,
8
+ :currency,
9
9
  :description,
10
10
  :name,
11
- :plan_id,
12
11
  :status,
13
12
  :gocardless_fees,
14
- :partner_fees
13
+ :partner_fees,
14
+ :amount_minus_fees,
15
+ :can_be_retried,
16
+ :can_be_cancelled,
17
+ :is_setup_fee
15
18
 
16
19
  # @attribute source_id
17
20
  # @return [String] the ID of the bill's source (eg subscription, pre_authorization)
18
21
  attr_accessor :source_id
22
+ attr_accessor :source_type
19
23
 
20
- reference_accessor :merchant_id, :user_id, :payment_id, :payout_id
21
- date_accessor :created_at, :paid_at
24
+ reference_accessor :merchant_id, :user_id, :payout_id
25
+ date_accessor :created_at, :paid_at, :charge_customer_at
26
+
27
+ # Alias getter methods
28
+ alias_method :is_setup_fee?, :is_setup_fee
29
+ alias_method :can_be_cancelled?, :can_be_cancelled
30
+ alias_method :can_be_retried?, :can_be_retried
22
31
 
23
32
  def source
24
33
  klass = GoCardless.const_get(Utils.camelize(source_type.to_s))
@@ -47,7 +56,7 @@ module GoCardless
47
56
 
48
57
  # The ability to refund a payment is disabled by default.
49
58
  #
50
- # Please contact help@gocardless.com if you require access to
59
+ # Please contact help@gocardless.com if you require access to
51
60
  # the refunds API endpoint.
52
61
  def refund!
53
62
  path = self.class.endpoint.gsub(':id', id.to_s) + '/refund'
@@ -55,14 +64,17 @@ module GoCardless
55
64
  end
56
65
 
57
66
  def save
58
- save_data({
59
- :bill => {
60
- :pre_authorization_id => self.source_id,
61
- :amount => self.amount,
62
- :name => self.name,
63
- :description => self.description,
64
- }
65
- })
67
+ bill_params = {
68
+ :pre_authorization_id => self.source_id,
69
+ :amount => self.amount,
70
+ :name => self.name,
71
+ :description => self.description,
72
+ :charge_customer_at => self.charge_customer_at,
73
+ }
74
+
75
+ bill_params.delete_if { |_,v| v.nil? }
76
+
77
+ save_data({ :bill => bill_params })
66
78
  self
67
79
  end
68
80
 
@@ -117,7 +117,7 @@ module GoCardless
117
117
  # @param [Hash] params query string parameters
118
118
  # @return [Hash] hash the parsed response data
119
119
  def api_get(path, params = {})
120
- request(:get, "#{API_PATH}#{path}", :params => params).parsed
120
+ api_request(:get, path, :params => params).parsed
121
121
  end
122
122
 
123
123
  # Issue a POST request to the API server
@@ -127,7 +127,7 @@ module GoCardless
127
127
  # @param [Hash] data a hash of data that will be sent as the request body
128
128
  # @return [Hash] hash the parsed response data
129
129
  def api_post(path, data = {})
130
- request(:post, "#{API_PATH}#{path}", :data => data).parsed
130
+ api_request(:post, path, :data => data).parsed
131
131
  end
132
132
 
133
133
  # Issue a PUT request to the API server
@@ -137,7 +137,7 @@ module GoCardless
137
137
  # @param [Hash] data a hash of data that will be sent as the request body
138
138
  # @return [Hash] hash the parsed response data
139
139
  def api_put(path, data = {})
140
- request(:put, "#{API_PATH}#{path}", :data => data).parsed
140
+ api_request(:put, path, :data => data).parsed
141
141
  end
142
142
 
143
143
  # Issue a DELETE request to the API server
@@ -147,7 +147,18 @@ module GoCardless
147
147
  # @param [Hash] data a hash of data that will be sent as the request body
148
148
  # @return [Hash] hash the parsed response data
149
149
  def api_delete(path, data = {})
150
- request(:delete, "#{API_PATH}#{path}", :data => data).parsed
150
+ api_request(:delete, path, :data => data).parsed
151
+ end
152
+
153
+
154
+ # Issue a request to the API server, returning the full response
155
+ #
156
+ # @note this method is for internal use
157
+ # @param [Symbol] method the HTTP method to use (e.g. +:get+, +:post+)
158
+ # @param [String] path the path that will be added to the API prefix
159
+ # @option [Hash] opts additional request options (e.g. form data, params)
160
+ def api_request(method, path, opts = {})
161
+ request(method, "#{API_PATH}#{path}", opts)
151
162
  end
152
163
 
153
164
  # @method merchant
@@ -185,13 +196,6 @@ module GoCardless
185
196
  Bill.find_with_client(self, id)
186
197
  end
187
198
 
188
- # @method payment(id)
189
- # @param [String] id of the payment
190
- # @return [Payment] the payment matching the id requested
191
- def payment(id)
192
- Payment.find_with_client(self, id)
193
- end
194
-
195
199
  # Create a new bill under a given pre-authorization
196
200
  # @see PreAuthorization#create_bill
197
201
  #
@@ -239,7 +243,7 @@ module GoCardless
239
243
  end
240
244
 
241
245
  # Confirm a newly-created subscription, pre-authorzation or one-off
242
- # payment. This method also checks that the resource response data includes
246
+ # bill. This method also checks that the resource response data includes
243
247
  # a valid signature and will raise a {SignatureError} if the signature is
244
248
  # invalid.
245
249
  #
@@ -11,6 +11,7 @@ module GoCardless
11
11
  :pending_balance,
12
12
  :next_payout_amount,
13
13
  :hide_variable_amount
14
+
14
15
  date_accessor :created_at, :next_payout_date
15
16
  end
16
17
  end
@@ -0,0 +1,43 @@
1
+ module GoCardless
2
+ class Page
3
+ include Enumerable
4
+
5
+ def initialize(resource_class, data, links)
6
+ @resource_class = resource_class
7
+ @data = data
8
+ @links = links
9
+ end
10
+
11
+ # The next page number, nil if there is no next page
12
+ def next_page
13
+ @links['next']
14
+ end
15
+
16
+ # The previous page number, nil if there is no previous page
17
+ def previous_page
18
+ @links['previous']
19
+ end
20
+
21
+ # The first page number, nil if this is the first page
22
+ def first_page
23
+ @links['first']
24
+ end
25
+
26
+ # The last page number, nil if this is the last page
27
+ def last_page
28
+ @links['last']
29
+ end
30
+
31
+ # Used for page iteration
32
+ def has_next?
33
+ !!@links['next']
34
+ end
35
+
36
+ # Yield each of the items in the page as instances of the resource class
37
+ def each(&block)
38
+ @data.each do |attrs|
39
+ yield @resource_class.new(attrs)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,86 @@
1
+ require 'multi_json'
2
+ require 'gocardless/page'
3
+
4
+ module GoCardless
5
+ class Paginator
6
+ include Enumerable
7
+
8
+ attr_reader :num_records
9
+ attr_reader :num_pages
10
+
11
+ DEFAULT_PAGE_NUMBER = 1
12
+ DEFAULT_PAGE_SIZE = 30
13
+
14
+ def initialize(client, resource_class, path, query)
15
+ @client = client
16
+ @resource_class = resource_class
17
+ @path, @query = path, query
18
+ @page_number, @per_page = DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE
19
+ end
20
+
21
+ # Set the number of records per page (page size), if an argument is
22
+ # provided. Returns the current per_page value, whether an argument is
23
+ # provided or not.
24
+ def per_page(results_per_page = nil)
25
+ if results_per_page
26
+ @num_records, @num_pages = nil, nil
27
+ @per_page = results_per_page
28
+ self
29
+ else
30
+ @per_page
31
+ end
32
+ end
33
+
34
+ # Fetch and return a single page.
35
+ def load_page(page_num)
36
+ params = @query.merge(pagination_params(page_num))
37
+ response = @client.api_request(:get, @path, :params => params)
38
+
39
+ metadata = parse_metadata(response)
40
+ @num_records, @num_pages = metadata['records'], metadata['pages']
41
+
42
+ Page.new(@resource_class, response.parsed, metadata['links'])
43
+ end
44
+
45
+ alias_method :page, :load_page
46
+
47
+ # Yield every record from every current page, auto-fetching new pages as
48
+ # the iteration happens. Records are returned as instances of the
49
+ # appropriate resource classes (e.g. Subscription).
50
+ def each(&block)
51
+ each_page { |page| page.each(&block) }
52
+ end
53
+
54
+ # Fetch and yield each page of results.
55
+ def each_page
56
+ page_obj = load_page(1)
57
+ loop do
58
+ yield page_obj
59
+ break unless page_obj.has_next?
60
+ page_obj = load_page(page_obj.next_page)
61
+ end
62
+ end
63
+
64
+ # Return the total number of records. May trigger an HTTP request.
65
+ def count
66
+ load_page(1) if @num_records.nil? # load pagination metadata
67
+ @num_records
68
+ end
69
+
70
+ # Return the total number of pages. May trigger an HTTP request.
71
+ def page_count
72
+ load_page(1) if @num_records.nil? # load pagination metadata
73
+ @num_pages
74
+ end
75
+
76
+ private
77
+
78
+ def pagination_params(page_num)
79
+ { :page => page_num, :per_page => @per_page }
80
+ end
81
+
82
+ def parse_metadata(response)
83
+ MultiJson.load(response.headers['X-Pagination'])
84
+ end
85
+ end
86
+ end
@@ -9,9 +9,9 @@ module GoCardless
9
9
  :interval_unit,
10
10
  :name,
11
11
  :description,
12
- :plan_id,
13
12
  :status,
14
- :remaining_amount
13
+ :remaining_amount,
14
+ :setup_fee
15
15
 
16
16
  reference_accessor :merchant_id, :user_id
17
17
 
@@ -1,4 +1,5 @@
1
1
  require 'date'
2
+ require 'gocardless/paginator'
2
3
 
3
4
  module GoCardless
4
5
  class Resource
@@ -18,18 +19,7 @@ module GoCardless
18
19
  path = uri.path.sub(%r{^/api/v\d+}, '')
19
20
 
20
21
  # Modify the instance's metaclass to add the method
21
- metaclass = class << self; self; end
22
- metaclass.send(:define_method, name) do |*args|
23
- # 'name' will be something like 'bills', convert it to Bill and
24
- # look up the resource class with that name
25
- class_name = Utils.camelize(Utils.singularize(name.to_s))
26
- klass = GoCardless.const_get(class_name)
27
- query = default_query.merge(args.first || {})
28
- client.api_get(path, query).map do |attrs|
29
- # Convert the results to instances of the looked-up class
30
- klass.new_with_client(client, attrs)
31
- end
32
- end
22
+ define_paginated_resource_method(name, path, default_query)
33
23
  end
34
24
 
35
25
  # Set resource attribute values
@@ -182,5 +172,21 @@ module GoCardless
182
172
  response = client.send("api_#{method}", path, data)
183
173
  response.each { |key,val| send("#{key}=", val) if respond_to?("#{key}=") } if response.is_a? Hash
184
174
  end
175
+
176
+ def define_paginated_resource_method(name, path, default_query)
177
+ metaclass = class << self; self; end
178
+ metaclass.send(:define_method, name) do |*args|
179
+ # 'name' will be something like 'bills', convert it to Bill and
180
+ # look up the resource class with that name
181
+ class_name = Utils.camelize(Utils.singularize(name.to_s))
182
+ klass = GoCardless.const_get(class_name)
183
+
184
+ # merge the default query, which may have been included in the
185
+ # sub_resource_uri, with the query params provided by the user
186
+ query = default_query.merge(args.first || {})
187
+
188
+ Paginator.new(client, self, path, query)
189
+ end
190
+ end
185
191
  end
186
192
  end
@@ -9,17 +9,13 @@ module GoCardless
9
9
  :interval_unit,
10
10
  :name,
11
11
  :description,
12
- :plan_id,
13
12
  :status,
14
- :setup_fee,
15
- :trial_length,
16
- :trial_unit
13
+ :setup_fee
17
14
 
18
15
  reference_accessor :merchant_id, :user_id
19
16
 
20
17
  date_accessor :start_at, :expires_at, :created_at, :next_interval_start
21
18
 
22
-
23
19
  def cancel!
24
20
  path = self.class.endpoint.gsub(':id', id.to_s) + '/cancel'
25
21
  client.api_put(path)
@@ -2,7 +2,12 @@ module GoCardless
2
2
  class User < Resource
3
3
  self.endpoint = '/users/:id'
4
4
 
5
- attr_accessor :name, :first_name, :last_name, :email
5
+ attr_accessor :name,
6
+ :first_name,
7
+ :last_name,
8
+ :company_name,
9
+ :email
10
+
6
11
  date_accessor :created_at
7
12
 
8
13
  def name
@@ -1,3 +1,3 @@
1
1
  module GoCardless
2
- VERSION = '1.9.0'.freeze
2
+ VERSION = '1.10.0'.freeze
3
3
  end
@@ -1,96 +1,46 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe GoCardless::Bill do
4
- before :each do
5
- @app_id = 'abc'
6
- @app_secret = 'xyz'
7
- GoCardless.account_details = {:app_id => @app_id, :app_secret => @app_secret,
8
- :token => 'xxx', :merchant_id => '1'}
9
- @client = GoCardless.client
4
+ before do
5
+ GoCardless.account_details = {:app_id => 'abc', :app_secret => 'xyz',
6
+ :token => 'xxx', :merchant_id => '123'}
10
7
  end
8
+ let(:client) { GoCardless.client }
9
+ let(:bill) { GoCardless::Bill.new(:id => 123) }
11
10
 
12
11
  it "source getter works" do
13
- b = GoCardless::Bill.new(:source_type => :subscription, :source_id => 123)
14
- @client.access_token = 'TOKEN'
15
- @client.merchant_id = '123'
16
- stub_get(@client, :id => 123)
17
- source = b.source
12
+ bill.source_id = 123
13
+ bill.source_type = :subscription
14
+ stub_get(client, :id => 123)
15
+ source = bill.source
18
16
  source.should be_a GoCardless::Subscription
19
17
  source.id.should == 123
20
18
  end
21
19
 
22
20
  it "source setter works" do
23
- b = GoCardless::Bill.new
24
- b.source = GoCardless::Subscription.new(:id => 123)
25
- b.source_id.should == 123
26
- b.source_type.should.to_s == 'subscription'
21
+ bill.source = GoCardless::Subscription.new(:id => 123)
22
+ bill.source_id.should == 123
23
+ bill.source_type.should.to_s == 'subscription'
27
24
  end
28
25
 
29
26
  it "should be able to be retried" do
30
- b = GoCardless::Bill.new(:id => 123)
31
- @client.should_receive(:api_post).with('/bills/123/retry')
32
- b.retry!
27
+ client.should_receive(:api_post).with('/bills/123/retry')
28
+ bill.retry!
33
29
  end
34
30
 
35
31
  it "should be able to be cancelled" do
36
- b = GoCardless::Bill.new(:id => 123)
37
- @client.should_receive(:api_put).with('/bills/123/cancel')
38
- b.cancel!
32
+ client.should_receive(:api_put).with('/bills/123/cancel')
33
+ bill.cancel!
39
34
  end
40
35
 
41
36
  it "should be able to be refunded" do
42
- b = GoCardless::Bill.new(:id => 123)
43
- @client.should_receive(:api_post).with('/bills/123/refund')
44
- b.refund!
37
+ client.should_receive(:api_post).with('/bills/123/refund')
38
+ bill.refund!
45
39
  end
46
40
 
47
- describe "pending query method" do
48
- it "and_return true when the subscription status is pending" do
49
- GoCardless::Bill.new(:status => 'pending').pending?.should be_true
50
- end
51
-
52
- it "and_return false otherwise" do
53
- GoCardless::Bill.new.pending?.should be_false
54
- end
55
- end
56
-
57
- describe "paid query method" do
58
- it "and_return true when the subscription status is paid" do
59
- GoCardless::Bill.new(:status => 'paid').paid?.should be_true
60
- end
61
-
62
- it "and_return false otherwise" do
63
- GoCardless::Bill.new.paid?.should be_false
64
- end
65
- end
66
-
67
- describe "failed query method" do
68
- it "and_return true when the subscription status is failed" do
69
- GoCardless::Bill.new(:status => 'failed').failed?.should be_true
70
- end
71
-
72
- it "and_return false otherwise" do
73
- GoCardless::Bill.new.failed?.should be_false
74
- end
75
- end
76
-
77
- describe "withdrawn query method" do
78
- it "and_return true when the subscription status is withdrawn" do
79
- GoCardless::Bill.new(:status => 'withdrawn').withdrawn?.should be_true
80
- end
81
-
82
- it "and_return false otherwise" do
83
- GoCardless::Bill.new.withdrawn?.should be_false
84
- end
85
- end
86
-
87
- describe "refunded query method" do
88
- it "and_return true when the subscription status is refunded" do
89
- GoCardless::Bill.new(:status => 'refunded').refunded?.should be_true
90
- end
91
-
92
- it "and_return false otherwise" do
93
- GoCardless::Bill.new.refunded?.should be_false
94
- end
95
- end
41
+ it_behaves_like "it has a query method for", "pending"
42
+ it_behaves_like "it has a query method for", "paid"
43
+ it_behaves_like "it has a query method for", "failed"
44
+ it_behaves_like "it has a query method for", "withdrawn"
45
+ it_behaves_like "it has a query method for", "refunded"
96
46
  end