rspreedly 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +48 -0
  6. data/VERSION +1 -0
  7. data/lib/rspreedly/base.rb +76 -0
  8. data/lib/rspreedly/complimentary_subscription.rb +5 -0
  9. data/lib/rspreedly/complimentary_time_extension.rb +5 -0
  10. data/lib/rspreedly/config.rb +84 -0
  11. data/lib/rspreedly/error.rb +9 -0
  12. data/lib/rspreedly/invoice.rb +61 -0
  13. data/lib/rspreedly/line_item.rb +5 -0
  14. data/lib/rspreedly/payment_method.rb +7 -0
  15. data/lib/rspreedly/subscriber.rb +153 -0
  16. data/lib/rspreedly/subscription_plan.rb +40 -0
  17. data/lib/rspreedly.rb +29 -0
  18. data/spec/config_spec.rb +144 -0
  19. data/spec/fixtures/complimentary_failed_active.xml +1 -0
  20. data/spec/fixtures/complimentary_failed_inactive.xml +1 -0
  21. data/spec/fixtures/complimentary_not_valid.xml +3 -0
  22. data/spec/fixtures/complimentary_success.xml +25 -0
  23. data/spec/fixtures/create_subscriber.xml +25 -0
  24. data/spec/fixtures/existing_subscriber.xml +1 -0
  25. data/spec/fixtures/free_plan_not_elligable.xml +1 -0
  26. data/spec/fixtures/free_plan_not_free.xml +1 -0
  27. data/spec/fixtures/free_plan_not_set.xml +1 -0
  28. data/spec/fixtures/free_plan_success.xml +25 -0
  29. data/spec/fixtures/invalid_subscriber.xml +1 -0
  30. data/spec/fixtures/invalid_update.xml +1 -0
  31. data/spec/fixtures/invoice_created.xml +43 -0
  32. data/spec/fixtures/invoice_invalid.xml +1 -0
  33. data/spec/fixtures/no_plans.xml +2 -0
  34. data/spec/fixtures/no_subscribers.xml +2 -0
  35. data/spec/fixtures/payment_already_paid.xml +1 -0
  36. data/spec/fixtures/payment_invalid.xml +1 -0
  37. data/spec/fixtures/payment_not_found.xml +1 -0
  38. data/spec/fixtures/payment_success.xml +43 -0
  39. data/spec/fixtures/plan_disabled.xml +1 -0
  40. data/spec/fixtures/plan_not_found.xml +1 -0
  41. data/spec/fixtures/subscriber.xml +25 -0
  42. data/spec/fixtures/subscriber_not_found.xml +1 -0
  43. data/spec/fixtures/subscribers.xml +75 -0
  44. data/spec/fixtures/subscription_plan_list.xml +91 -0
  45. data/spec/invoice_spec.rb +129 -0
  46. data/spec/spec_helper.rb +44 -0
  47. data/spec/subscriber_spec.rb +442 -0
  48. data/spec/subscription_plan_spec.rb +36 -0
  49. metadata +107 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Richard Livsey
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.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ = RSpreedly
2
+
3
+ Ruby library to access the Spreedly API (all of it).
4
+
5
+ == Why another one?
6
+
7
+ There are a few of these knocking about, but I couldn't find one particular to my needs:
8
+
9
+ * Well covered with specs (aiming for 100%)
10
+ * Covers the entire API, not just parts of it
11
+ * Rubyish/ActiveRecord style access
12
+
13
+ == Usage
14
+
15
+ Configure your API key and site name for your account:
16
+
17
+ RSpreedly::Config.setup do |config|
18
+ config.api_key = "your-api-key"
19
+ config.site_name = "your-site-name"
20
+ end
21
+
22
+ List subscribers
23
+
24
+ RSpreedly::Subscriber.find(:all).each do |subscriber|
25
+ # do something
26
+ end
27
+
28
+ CRUD access to subscribers
29
+
30
+ sub = RSpreedly::Subscriber.new(:customer_id => 42, :email => "somewhere@example.com")
31
+ sub.token => nil
32
+ sub.save
33
+ sub.token => "6af9994a57e420345897b1abb4c27a9db27fa4d0"
34
+
35
+ sub = RSpreedly::Subscriber.find(42)
36
+ sub.email = "new-email@example.com"
37
+ sub.save
38
+
39
+ sub = RSpreedly::Subscriber.find(69)
40
+ sub.destroy
41
+
42
+ Comp subscriptions
43
+
44
+ comp = RSpreedly::ComplimentarySubscription.new(:duration_quantity => 3, :duration_units => "months", :feature_level => "Pro")
45
+ sub = RSpreedly::Subscriber.find(69)
46
+ sub.comp_subscription(comp)
47
+
48
+ View all plans
49
+
50
+ plans = RSpreedly::SubscriptionPlan.find(:all)
51
+
52
+ Raise an invoice, and pay it
53
+
54
+ invoice = Invoice.new(:subscription_plan_id => 5, :subscriber => sub)
55
+ invoice.save
56
+
57
+ payment = RSpreedly::PaymentMethod::CreditCard(:card_type => 'visa', :number => '123456', ...)
58
+ invoice.pay(payment)
59
+
60
+ See the specs and API docs at Spreedly for more details and the rest of the things it can do.
61
+
62
+ https://www.spreedly.com/manual/integration-reference/url-reference/
63
+
64
+ == Todo
65
+
66
+ * Better specs for data we send to Spreedly.
67
+ * Better docs.
68
+
69
+ == Thanks
70
+
71
+ I studied the other Spreedly APIs and there may well be a line or three this library has in common with:
72
+
73
+ * http://github.com/terralien/spreedly-gem
74
+ * http://github.com/erbmicha/spreedly/
75
+
76
+ == Copyright
77
+
78
+ Copyright (c) 2009 Richard Livsey. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rspreedly"
8
+ gem.summary = %Q{Ruby library for the Spreedly API}
9
+ gem.email = "richard@livsey.org"
10
+ gem.homepage = "http://github.com/rlivsey/rspreedly"
11
+ gem.authors = ["Richard Livsey"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'spec/rake/spectask'
20
+ Spec::Rake::SpecTask.new(:spec) do |spec|
21
+ spec.libs << 'lib' << 'spec'
22
+ spec.spec_files = FileList['spec/**/*_spec.rb']
23
+ end
24
+
25
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.pattern = 'spec/**/*_spec.rb'
28
+ spec.rcov = true
29
+ end
30
+
31
+
32
+ task :default => :spec
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ if File.exist?('VERSION.yml')
37
+ config = YAML.load(File.read('VERSION.yml'))
38
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
39
+ else
40
+ version = ""
41
+ end
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "RSpreedly #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
48
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,76 @@
1
+ module RSpreedly
2
+
3
+ class Base
4
+ include HTTParty
5
+ format :xml
6
+ base_uri "https://spreedly.com/api/v4"
7
+
8
+ def self.api_request(type, path, options={})
9
+ path = "#{RSpreedly::Config.site_name}#{path}"
10
+ options.merge!({
11
+ :basic_auth => {:username => RSpreedly::Config.api_key, :password => 'X'},
12
+ :headers => {"Content-Type" => 'application/xml'}
13
+ })
14
+ self.do_request(type, path, options)
15
+ end
16
+
17
+ def self.do_request(type, path, options)
18
+ response = self.send(type.to_s, path, options)
19
+ message = "#{response.code}: #{response.body}"
20
+
21
+ case response.code.to_i
22
+ when 403
23
+ raise(RSpreedly::Error::Forbidden.new, message)
24
+ when 422
25
+ raise(RSpreedly::Error::BadRequest.new, message)
26
+ when 404
27
+ raise(RSpreedly::Error::NotFound.new, message)
28
+ end
29
+
30
+ response
31
+ end
32
+
33
+ def initialize(attrs={})
34
+ self.attributes = attrs
35
+ end
36
+
37
+ def attributes=(attrs)
38
+ attrs.each do |k, v|
39
+ self.send("#{k}=", v)
40
+ end
41
+ end
42
+
43
+ def api_request(type, path, options={})
44
+ self.class.api_request(type, path, options)
45
+ end
46
+
47
+ # TODO - do this nicer
48
+ # rather eew at the moment and hand made XML is not nice
49
+ def to_xml(opts={})
50
+ exclude = opts[:exclude] || []
51
+
52
+ tag = opts[:tag] || RSpreedly.underscore(self.class.to_s)
53
+ inner = opts[:inner]
54
+ outer = opts[:outer]
55
+ no_tag = opts[:no_tag]
56
+
57
+ xml = ""
58
+ xml << "<#{outer}>" if outer
59
+ xml << "<#{tag}>" unless no_tag
60
+ xml << "<#{inner}>" if inner
61
+ self.instance_variables.each do |var|
62
+ name = var.gsub('@', '')
63
+ next if exclude.include?(name.to_sym)
64
+ value = self.instance_variable_get(var)
65
+ if value.respond_to?(:to_xml)
66
+ value = value.to_xml(:no_tag => (RSpreedly.underscore(value.class.to_s) == name))
67
+ end
68
+ xml << "<#{name}>#{value}</#{name}>"
69
+ end
70
+ xml << "</#{inner}>" if inner
71
+ xml << "</#{tag}>" unless no_tag
72
+ xml << "</#{outer}>" if outer
73
+ xml
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,5 @@
1
+ module RSpreedly
2
+ class ComplimentarySubscription < Base
3
+ attr_accessor :duration_quantity, :duration_units, :feature_level
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module RSpreedly
2
+ class ComplimentaryTimeExtension < Base
3
+ attr_accessor :duration_quantity, :duration_units
4
+ end
5
+ end
@@ -0,0 +1,84 @@
1
+ module RSpreedly
2
+ module Config
3
+ class << self
4
+
5
+ # the configuration hash itself
6
+ def configuration
7
+ @configuration ||= defaults
8
+ end
9
+
10
+ def defaults
11
+ {
12
+ :logger => defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : Logger.new(STDOUT),
13
+ :debug => false,
14
+ :site_name => nil, # your site name
15
+ :key => nil # your API key
16
+ }
17
+ end
18
+
19
+ def [](key)
20
+ configuration[key]
21
+ end
22
+
23
+ def []=(key, val)
24
+ configuration[key] = val
25
+ end
26
+
27
+ # remove an item from the configuration
28
+ def delete(key)
29
+ configuration.delete(key)
30
+ end
31
+
32
+ # Return the value of the key, or the default if doesn't exist
33
+ #
34
+ # ==== Examples
35
+ #
36
+ # RSpreedly::Config.fetch(:monkey, false)
37
+ # => false
38
+ #
39
+ def fetch(key, default)
40
+ configuration.fetch(key, default)
41
+ end
42
+
43
+ def to_hash
44
+ configuration
45
+ end
46
+
47
+ # Yields the configuration.
48
+ #
49
+ # ==== Examples
50
+ # RSpreedly::Config.use do |config|
51
+ # config[:debug] = true
52
+ # config.something = false
53
+ # end
54
+ #
55
+ def setup
56
+ yield self
57
+ nil
58
+ end
59
+
60
+ def clear
61
+ @configuration = {}
62
+ end
63
+
64
+ def reset
65
+ @configuration = defaults
66
+ end
67
+
68
+ # allow getting and setting properties via RSpreedly::Config.xxx
69
+ #
70
+ # ==== Examples
71
+ # RSpreedly::Config.debug
72
+ # RSpreedly::Config.debug = false
73
+ #
74
+ def method_missing(method, *args)
75
+ if method.to_s[-1,1] == '='
76
+ configuration[method.to_s.tr('=','').to_sym] = *args
77
+ else
78
+ configuration[method]
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,9 @@
1
+ module RSpreedly
2
+ module Error
3
+ class Base < StandardError; end
4
+ class Forbidden < Base; end # 403 errors
5
+ class BadRequest < Base; end # 422 errors
6
+ class NotFound < Base; end # 404 errors
7
+ class GatewayTimeout < Base; end # 504 errors
8
+ end
9
+ end
@@ -0,0 +1,61 @@
1
+ module RSpreedly
2
+
3
+ class Invoice < Base
4
+
5
+ attr_accessor :subscription_plan_id,
6
+ :subscriber,
7
+ :closed,
8
+ :created_at,
9
+ :token,
10
+ :updated_at,
11
+ :price,
12
+ :amount,
13
+ :currency_code,
14
+ :line_items
15
+
16
+ # Create an Invoice (more)
17
+ # POST /api/v4/[short site name]/invoices.xml
18
+ def create
19
+ begin
20
+ create!
21
+ rescue RSpreedly::Error::Base
22
+ # gulp those errors down
23
+ # TODO - set self.errors or something?
24
+ end
25
+ end
26
+
27
+ def create!
28
+ result = api_request(:post, "/invoices.xml", :body => self.to_xml)
29
+ self.attributes = result["invoice"]
30
+ true
31
+ end
32
+
33
+ alias_method :save, :create
34
+ alias_method :save!, :create!
35
+
36
+ def subscriber=(data)
37
+ if data.is_a? Hash
38
+ data = RSpreedly::Subscriber.new(data)
39
+ end
40
+ @subscriber = data
41
+ end
42
+
43
+ def line_items=(data)
44
+ @line_items = []
45
+ data.each do |item|
46
+ if item.is_a? Hash
47
+ item = RSpreedly::LineItem.new(item)
48
+ end
49
+ @line_items << item
50
+ end
51
+ end
52
+
53
+ # Pay an Invoice (more)
54
+ # PUT /api/v4/[short site name]/invoices/[invoice token]/pay.xml
55
+ def pay(payment)
56
+ result = api_request(:put, "/invoices/#{self.token}/pay.xml", :body => payment.to_xml(:outer => 'payment'))
57
+ self.attributes = result["invoice"]
58
+ true
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,5 @@
1
+ module RSpreedly
2
+ class LineItem < Base
3
+ attr_accessor :price, :notes, :amount, :description, :currency_code
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module RSpreedly
2
+ module PaymentMethod
3
+ class CreditCard < Base
4
+ attr_accessor :number, :verification_value, :month, :year, :first_name, :last_name, :card_type
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,153 @@
1
+ module RSpreedly
2
+
3
+ class Subscriber < Base
4
+
5
+ attr_accessor :active,
6
+ :active_until,
7
+ :billing_first_name,
8
+ :billing_last_name,
9
+ :card_expires_before_next_auto_renew,
10
+ :created_at,
11
+ :customer_id,
12
+ :eligible_for_free_trial,
13
+ :email,
14
+ :feature_level,
15
+ :grace_until,
16
+ :in_grace_period,
17
+ :lifetime_subscription,
18
+ :new_customer_id,
19
+ :on_trial,
20
+ :payment_method,
21
+ :ready_to_renew,
22
+ :recurring,
23
+ :screen_name,
24
+ :store_credit,
25
+ :store_credit_currency_code,
26
+ :subscription_plan_name,
27
+ :token,
28
+ :updated_at
29
+
30
+ class << self
31
+
32
+ # Get a subscriber’s details
33
+ # GET /api/v4/[short site name]/subscribers/[subscriber id].xml
34
+ def find(id)
35
+ return all if id == :all
36
+
37
+ begin
38
+ data = api_request(:get, "/subscribers/#{id}.xml")
39
+ Subscriber.new(data["subscriber"])
40
+ rescue RSpreedly::Error::NotFound
41
+ nil
42
+ end
43
+ end
44
+
45
+ # Get a list of all subscribers (more)
46
+ # GET /api/v4/[short site name]/subscribers.xml
47
+ def all
48
+ response = api_request(:get, "/subscribers.xml")
49
+ return [] unless response.has_key?("subscribers")
50
+ response["subscribers"].collect{|data| Subscriber.new(data)}
51
+ end
52
+
53
+ # Clear all subscribers from a *test* site (more)
54
+ # DELETE /api/v4/[short site name]/subscribers.xml
55
+ def delete_all
56
+ !! api_request(:delete, "/subscribers.xml")
57
+ end
58
+
59
+ alias_method :destroy_all, :delete_all
60
+
61
+ end
62
+
63
+ def new_record?
64
+ !self.token
65
+ end
66
+
67
+ def save
68
+ self.new_record? ? self.create : self.update
69
+ end
70
+
71
+ # Create a subscriber (more)
72
+ # POST /api/v4/[short site name]/subscribers.xml
73
+ def create!
74
+ result = api_request(:post, "/subscribers.xml", :body => self.to_xml)
75
+ self.attributes = result["subscriber"]
76
+ true
77
+ end
78
+
79
+ def create
80
+ begin
81
+ create!
82
+ rescue RSpreedly::Error::Base
83
+ # gulp those errors down
84
+ # TODO - set self.errors or something?
85
+ end
86
+ end
87
+
88
+ # Update a Subscriber (more)
89
+ # PUT /api/v4/[short site name]/subscribers/[subscriber id].xml
90
+ def update!
91
+ !! api_request(:put, "/subscribers/#{self.customer_id}.xml", :body => self.to_xml(:exclude => [:customer_id]))
92
+ end
93
+
94
+ def update
95
+ begin
96
+ update!
97
+ rescue RSpreedly::Error::Base
98
+ # gulp those errors down
99
+ # TODO - set self.errors or something?
100
+ end
101
+ end
102
+
103
+ # Delete one subscriber from a *test* site (more)
104
+ # DELETE /api/v4/[short site name]/subscribers/[subscriber id].xml
105
+ def destroy
106
+ begin
107
+ !! api_request(:delete, "/subscribers/#{self.customer_id}.xml")
108
+ rescue RSpreedly::Error::NotFound
109
+ nil
110
+ end
111
+ end
112
+ alias_method :delete, :destroy
113
+
114
+ # Give a subscriber a complimentary subscription (more)
115
+ # POST /api/v4/[short site name]/subscribers/[subscriber id]/complimentary_subscriptions.xml
116
+ def comp_subscription(subscription)
117
+ result = api_request(:post, "/subscribers/#{self.customer_id}/complimentary_subscriptions.xml", :body => subscription.to_xml)
118
+ self.attributes = result["subscriber"]
119
+ true
120
+ end
121
+
122
+ # Give a subscriber a complimentary time extension (more)
123
+ # POST /api/v4/[short site name]/subscribers/[subscriber id]/complimentary_time_extension.xml
124
+ def comp_time_extension(extension)
125
+ result = api_request(:post, "/subscribers/#{self.customer_id}/complimentary_time_extensions.xml", :body => extension.to_xml)
126
+ self.attributes = result["subscriber"]
127
+ true
128
+ end
129
+
130
+ # Programatically Stopping Auto Renew of a Subscriber (more)
131
+ # POST /api/v4/[short site name]/subscribers/[subscriber id]/stop_auto_renew.xml
132
+ def stop_auto_renew
133
+ !! api_request(:post, "/subscribers/#{self.customer_id}/stop_auto_renew.xml")
134
+ end
135
+
136
+ # Programatically Subscribe a Subscriber to a Free Trial Plan (more)
137
+ # POST /api/v4/[short site name]/subscribers/[subscriber id]/subscribe_to_free_trial.xml
138
+ def subscribe_to_free_trial(plan)
139
+ result = api_request(:post, "/subscribers/#{self.customer_id}/subscribe_to_free_trial.xml", :body => plan.to_xml)
140
+ self.attributes = result["subscriber"]
141
+ true
142
+ end
143
+
144
+ # Programatically Allow Another Free Trial (more)
145
+ # POST /api/v4/[short site name]/subscribers/[subscriber id]/allow_free_trial.xml
146
+ def allow_free_trial
147
+ result = api_request(:post, "/subscribers/#{self.customer_id}/allow_free_trial.xml")
148
+ self.attributes = result["subscriber"]
149
+ true
150
+ end
151
+
152
+ end
153
+ end
@@ -0,0 +1,40 @@
1
+ module RSpreedly
2
+
3
+ class SubscriptionPlan < Base
4
+
5
+ attr_accessor :amount,
6
+ :charge_after_first_period,
7
+ :charge_later_duration_quantity,
8
+ :charge_later_duration_units,
9
+ :created_at,
10
+ :currency_code,
11
+ :description,
12
+ :duration_quantity,
13
+ :duration_units,
14
+ :enabled,
15
+ :feature_level,
16
+ :force_recurring,
17
+ :id,
18
+ :name,
19
+ :needs_to_be_renewed,
20
+ :plan_type,
21
+ :price,
22
+ :return_url,
23
+ :terms,
24
+ :updated_at
25
+
26
+ # there's no API method for just getting one plan, so we fake it!
27
+ def self.find(id)
28
+ return all if id == :all
29
+ all.find{|plan| plan.id == id}
30
+ end
31
+
32
+ # Get a list of all subscription plans (more)
33
+ # GET /api/v4/[short site name]/subscription_plans.xml
34
+ def self.all
35
+ response = api_request(:get, "/subscription_plans.xml")
36
+ return [] unless response.has_key?("subscription_plans")
37
+ response["subscription_plans"].collect{|data| SubscriptionPlan.new(data)}
38
+ end
39
+ end
40
+ end
data/lib/rspreedly.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'logger'
2
+ require 'httparty'
3
+
4
+ require 'rspreedly/error'
5
+ require 'rspreedly/config'
6
+ require 'rspreedly/base'
7
+ require 'rspreedly/invoice'
8
+ require 'rspreedly/line_item'
9
+ require 'rspreedly/subscriber'
10
+ require 'rspreedly/subscription_plan'
11
+ require 'rspreedly/payment_method'
12
+ require 'rspreedly/complimentary_subscription'
13
+ require 'rspreedly/complimentary_time_extension'
14
+
15
+
16
+ module RSpreedly
17
+
18
+ # a few utility methods
19
+
20
+ # pretty much stolen from Rails
21
+ def self.underscore(camel_cased_word)
22
+ camel_cased_word.to_s.gsub(/\w+::/, '').
23
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
24
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
25
+ tr("-", "_").
26
+ downcase
27
+ end
28
+
29
+ end