servicemerchant 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE.txt +20 -0
- data/README.txt +231 -0
- data/Rakefile +122 -0
- data/demo.rb +69 -0
- data/recurring_billing/lib/am_extensions.rb +1 -0
- data/recurring_billing/lib/am_extensions/paypal_extension.rb +170 -0
- data/recurring_billing/lib/dependencies.rb +14 -0
- data/recurring_billing/lib/gateways.rb +5 -0
- data/recurring_billing/lib/gateways/authorize_net.rb +103 -0
- data/recurring_billing/lib/gateways/paypal.rb +124 -0
- data/recurring_billing/lib/recurring_billing.rb +130 -0
- data/recurring_billing/lib/recurring_billing.rdoc +87 -0
- data/recurring_billing/lib/utils.rb +81 -0
- data/recurring_billing/test/fixtures.yml +33 -0
- data/recurring_billing/test/remote/authorize_net_test.rb +36 -0
- data/recurring_billing/test/remote/paypal_test.rb +46 -0
- data/recurring_billing/test/remote/recurring_billing_test.rb +41 -0
- data/recurring_billing/test/test_helper.rb +153 -0
- data/recurring_billing/test/unit/authorize_net_gateway_class_test.rb +42 -0
- data/recurring_billing/test/unit/paypal_gateway_class_test.rb +23 -0
- data/recurring_billing/test/unit/recurring_billing_gateway_class_test.rb +35 -0
- data/recurring_billing/test/unit/utils_test.rb +17 -0
- data/subscription_management/Rakefile +29 -0
- data/subscription_management/lib/models/subscription.rb +9 -0
- data/subscription_management/lib/models/subscription_profile.rb +4 -0
- data/subscription_management/lib/subscription_management.rb +326 -0
- data/subscription_management/samples/backpack.yml +101 -0
- data/subscription_management/samples/basecamp.yml +71 -0
- data/subscription_management/samples/brainkeeper.yml +90 -0
- data/subscription_management/samples/campfire.yml +74 -0
- data/subscription_management/samples/clickandpledge.yml +24 -0
- data/subscription_management/samples/demo.rb +19 -0
- data/subscription_management/samples/elm.yml +174 -0
- data/subscription_management/samples/freshbooks.yml +78 -0
- data/subscription_management/samples/highrise.yml +100 -0
- data/subscription_management/samples/presets.yml +10 -0
- data/subscription_management/samples/tariff.outline.yml +0 -0
- data/subscription_management/samples/taxes.yml +21 -0
- data/subscription_management/subscription_management.rb +7 -0
- data/subscription_management/tasks/schema.rb +50 -0
- data/subscription_management/test/connection.rb +10 -0
- data/subscription_management/test/remote/subscription_management_test.rb +112 -0
- data/subscription_management/test/test_helper.rb +84 -0
- data/subscription_management/test/unit/subscription_management_test.rb +40 -0
- data/tracker/README +12 -0
- data/tracker/Rakefile +40 -0
- data/tracker/db/migrations/empty-directory +0 -0
- data/tracker/demo.rb +12 -0
- data/tracker/lib/models/recurring_payment_profile.rb +134 -0
- data/tracker/lib/models/transaction.rb +19 -0
- data/tracker/lib/recurring_billing_extension.rb +103 -0
- data/tracker/lib/recurring_billing_extension.rdoc +34 -0
- data/tracker/tasks/schema.rb +66 -0
- data/tracker/test/connection.rb +10 -0
- data/tracker/test/recurring_payment_profile.rb +35 -0
- data/tracker/test/remote/authorize_net_test.rb +68 -0
- data/tracker/test/remote/paypal_test.rb +115 -0
- data/tracker/test/test_helper.rb +87 -0
- data/tracker/test/unit/recurring_payment_profile_test.rb +62 -0
- data/tracker/tracker.rb +10 -0
- data/vendor/money-1.7.1/MIT-LICENSE +20 -0
- data/vendor/money-1.7.1/README +75 -0
- data/vendor/money-1.7.1/lib/bank/no_exchange_bank.rb +9 -0
- data/vendor/money-1.7.1/lib/bank/variable_exchange_bank.rb +30 -0
- data/vendor/money-1.7.1/lib/money.rb +29 -0
- data/vendor/money-1.7.1/lib/money/core_extensions.rb +26 -0
- data/vendor/money-1.7.1/lib/money/money.rb +209 -0
- data/vendor/money-1.7.1/lib/support/cattr_accessor.rb +57 -0
- metadata +153 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
# Tariff configuration for freshbooks
|
2
|
+
# http://www.freshbooks.com/pricing.php
|
3
|
+
#
|
4
|
+
|
5
|
+
freshbooks:
|
6
|
+
features:
|
7
|
+
clients: &clients
|
8
|
+
name: Active Clients
|
9
|
+
description: "Number of clients available for management"
|
10
|
+
staff: &staff
|
11
|
+
name: Staff Members
|
12
|
+
description: "Number of staff members who can access an account"
|
13
|
+
payment_terms:
|
14
|
+
monthly: &monthly
|
15
|
+
name: Monthly payments
|
16
|
+
periodicity: 1m
|
17
|
+
services:
|
18
|
+
shuttle_bus: &shuttle_bus
|
19
|
+
name: Shuttle Bus
|
20
|
+
features:
|
21
|
+
- feature: *clients
|
22
|
+
quantity: 25
|
23
|
+
- feature: *staff
|
24
|
+
quantity: 1
|
25
|
+
limousine: &limousine
|
26
|
+
name: Limousine
|
27
|
+
features:
|
28
|
+
- feature: *clients
|
29
|
+
quantity: 100
|
30
|
+
- feature: *staff
|
31
|
+
quantity: 2
|
32
|
+
private_jet: &private_jet
|
33
|
+
name: Private Jet
|
34
|
+
features:
|
35
|
+
- feature: *clients
|
36
|
+
quantity: 500
|
37
|
+
- feature: *staff
|
38
|
+
quantity: 3
|
39
|
+
starship: &starship
|
40
|
+
name: Starship
|
41
|
+
features:
|
42
|
+
- feature: *clients
|
43
|
+
quantity: 2000
|
44
|
+
- feature: *staff
|
45
|
+
quantity: 10
|
46
|
+
time_machine: &time_machine
|
47
|
+
name: Time Machine
|
48
|
+
features:
|
49
|
+
- feature: *clients
|
50
|
+
quantity: 5000
|
51
|
+
- feature: *staff
|
52
|
+
quantity: 20
|
53
|
+
tariff_plans:
|
54
|
+
shuttle_bus_monthly:
|
55
|
+
service: *shuttle_bus
|
56
|
+
payment_term: *monthly
|
57
|
+
currency: USD
|
58
|
+
price: 1400
|
59
|
+
limousine_monthly:
|
60
|
+
service: *limousine
|
61
|
+
payment_term: *monthly
|
62
|
+
currency: USD
|
63
|
+
price: 2700
|
64
|
+
private_jet_monthly:
|
65
|
+
service: *private_jet
|
66
|
+
payment_term: *monthly
|
67
|
+
currency: USD
|
68
|
+
price: 3900
|
69
|
+
starship_monthly:
|
70
|
+
service: *starship
|
71
|
+
payment_term: *monthly
|
72
|
+
currency: USD
|
73
|
+
price: 8900
|
74
|
+
time_machine_monthly:
|
75
|
+
service: *time_machine
|
76
|
+
payment_term: *monthly
|
77
|
+
currency: USD
|
78
|
+
price: 14900
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Tariff configuration for highrise
|
2
|
+
# http://www.highrisehq.com/signup
|
3
|
+
#
|
4
|
+
|
5
|
+
highrise:
|
6
|
+
features:
|
7
|
+
user: &user
|
8
|
+
name: User Accounts
|
9
|
+
description: "User accounts available within application"
|
10
|
+
storage: &storage
|
11
|
+
name: "File Storage"
|
12
|
+
unit: Gigabyte
|
13
|
+
description: "File storage maximum disk quota"
|
14
|
+
case: &case
|
15
|
+
name: Cases
|
16
|
+
description: "Cases let you keep related people, companies, notes, files, and images together on a convenient single page."
|
17
|
+
contact: &contact
|
18
|
+
name: Contacts
|
19
|
+
descrption: "Contacts for an account"
|
20
|
+
ssl: &ssl
|
21
|
+
name: SSL Security
|
22
|
+
description: "Whether SSL encryption for online sessions is available or not"
|
23
|
+
free_campfire_premium: &free_campfire_premium
|
24
|
+
name: Free Campfore Premium
|
25
|
+
description: "Free Premium Campfire membership. Campfire is real-time group chat tool for businesses."
|
26
|
+
payment_terms:
|
27
|
+
monthly: &monthly
|
28
|
+
name: Monthly payments
|
29
|
+
periodicity: 1m
|
30
|
+
trial_days: 30
|
31
|
+
services:
|
32
|
+
solo: &solo
|
33
|
+
name: Solo
|
34
|
+
features:
|
35
|
+
- feature: *user
|
36
|
+
quantity: 1
|
37
|
+
- feature: *storage
|
38
|
+
quantity: 3
|
39
|
+
- feature: *contact
|
40
|
+
quantity: 20000
|
41
|
+
- feature: *case
|
42
|
+
quantity: 0
|
43
|
+
- feature: *ssl
|
44
|
+
basic: &basic
|
45
|
+
name: Basic
|
46
|
+
features:
|
47
|
+
- feature: *user
|
48
|
+
quantity: 6
|
49
|
+
- feature: *storage
|
50
|
+
quantity: 3
|
51
|
+
- feature: *contact
|
52
|
+
quantity: 5000
|
53
|
+
- feature: *case
|
54
|
+
quantity: 5
|
55
|
+
plus: &plus
|
56
|
+
name: Plus
|
57
|
+
features:
|
58
|
+
- feature: *user
|
59
|
+
quantity: 15
|
60
|
+
- feature: *storage
|
61
|
+
quantity: 10
|
62
|
+
- feature: *contact
|
63
|
+
quantity: 20000
|
64
|
+
- feature: *case
|
65
|
+
quantity: 0
|
66
|
+
- feature: *ssl
|
67
|
+
pro: &pro
|
68
|
+
name: Pro
|
69
|
+
features:
|
70
|
+
- feature: *user
|
71
|
+
quantity: 40
|
72
|
+
- feature: *storage
|
73
|
+
quantity: 20
|
74
|
+
- feature: *contact
|
75
|
+
quantity: 30000
|
76
|
+
- feature: *case
|
77
|
+
quantity: 0
|
78
|
+
- feature: *ssl
|
79
|
+
- feature: *free_campfire_premium
|
80
|
+
tariff_plans:
|
81
|
+
solo_monthly:
|
82
|
+
service: *solo
|
83
|
+
payment_term: *monthly
|
84
|
+
currency: USD
|
85
|
+
price: 2900
|
86
|
+
basic_monthly:
|
87
|
+
service: *basic
|
88
|
+
payment_term: *monthly
|
89
|
+
currency: USD
|
90
|
+
price: 2400
|
91
|
+
plus_monthly:
|
92
|
+
service: *plus
|
93
|
+
payment_term: *monthly
|
94
|
+
currency: USD
|
95
|
+
price: 4900
|
96
|
+
pro_monthly:
|
97
|
+
service: *pro
|
98
|
+
payment_term: *monthly
|
99
|
+
currency: USD
|
100
|
+
price: 9900
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
defaults:
|
2
|
+
gst: &gst
|
3
|
+
name: Goods and Services Tax
|
4
|
+
tax1: &tax1
|
5
|
+
name: Sample tax
|
6
|
+
|
7
|
+
taxes:
|
8
|
+
ca:
|
9
|
+
name: non-resident, Canada
|
10
|
+
country: CA
|
11
|
+
state: *
|
12
|
+
taxes:
|
13
|
+
- tax: *gst
|
14
|
+
rate: 0.05
|
15
|
+
us_ca:
|
16
|
+
name: resident, CA
|
17
|
+
country: US
|
18
|
+
state: CA
|
19
|
+
taxes:
|
20
|
+
- tax: *tax1
|
21
|
+
rate: 0.2
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#TODO: Use auto-loading from activesupport
|
2
|
+
require 'rubygems'
|
3
|
+
require 'activerecord'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/lib/models/subscription'
|
6
|
+
require File.dirname(__FILE__) + '/lib/models/subscription_profile'
|
7
|
+
require File.dirname(__FILE__) + '/lib/subscription_management'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
namespace :subscription do
|
2
|
+
desc 'Create Subscription management database tables'
|
3
|
+
task :create_tables => :connection do
|
4
|
+
ActiveRecord::Base.connection.create_table :subscriptions, :force => true do |t|
|
5
|
+
t.column :account_id, :string, :null => false
|
6
|
+
t.column :tariff_plan_id, :string, :null => false
|
7
|
+
t.column :taxes_id, :string, :null => false
|
8
|
+
t.column :quantity, :integer, :null => false
|
9
|
+
t.column :currency, :string, :null => false
|
10
|
+
t.column :net_amount, :integer, :null => false
|
11
|
+
t.column :taxes_amount, :integer, :null => false
|
12
|
+
t.column :periodicity, :string, :null => false
|
13
|
+
t.column :starts_on, :date, :null => false
|
14
|
+
t.column :ends_on, :date
|
15
|
+
t.column :status, :string, :null => false
|
16
|
+
t.column :created_at, :datetime, :null => false
|
17
|
+
t.column :updated_at, :datetime
|
18
|
+
t.column :deleted_at, :datetime
|
19
|
+
end
|
20
|
+
ActiveRecord::Base.connection.add_index :subscriptions, [ :account_id ], :name => 'ix_subscription_account'
|
21
|
+
|
22
|
+
ActiveRecord::Base.connection.create_table :subscription_profiles, :force => true do |t|
|
23
|
+
t.column :subscription_id, :integer, :null => false
|
24
|
+
t.column :recurring_payment_profile_id, :integer, :null => false
|
25
|
+
t.column :created_at, :datetime, :null => false
|
26
|
+
end
|
27
|
+
ActiveRecord::Base.connection.add_index :subscription_profiles, [ :subscription_id ], :name => 'ix_subscription_profiles_subscription'
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Drop Subscription management database tables'
|
31
|
+
task :drop_tables => :connection do
|
32
|
+
ActiveRecord::Base.connection.drop_table :subscription_profiles
|
33
|
+
ActiveRecord::Base.connection.drop_table :subscriptions
|
34
|
+
end
|
35
|
+
|
36
|
+
# Use Rails connection when appropriate or fallback to local test db
|
37
|
+
task :connection do
|
38
|
+
connected = false
|
39
|
+
begin
|
40
|
+
begin
|
41
|
+
connected = true if ActiveRecord::Base.connection
|
42
|
+
rescue ActiveRecord::ConenctionNotEstablished
|
43
|
+
end
|
44
|
+
rescue NameError # ActiveRecord not loaded
|
45
|
+
end
|
46
|
+
require File.dirname(__FILE__) + "/../test/connection" unless connected
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# As we're not using Rails in tests, we have to establish DB conneciton ourselves
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'activerecord'
|
4
|
+
require 'activerecord'
|
5
|
+
gem 'sqlite3-ruby'
|
6
|
+
|
7
|
+
ActiveRecord::Base.establish_connection(
|
8
|
+
:adapter => "sqlite3",
|
9
|
+
:database => (File.dirname(__FILE__) + "/../../tracker/db/test.db")
|
10
|
+
)
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
require 'money'
|
4
|
+
|
5
|
+
class SubscriptionManagementRemoteTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@sm = ::SubscriptionManagement.new(
|
9
|
+
:tariff_plans_config => File.dirname(__FILE__) + '/../../samples/backpack.yml',
|
10
|
+
:taxes_config => File.dirname(__FILE__) + '/../../samples/taxes.yml',
|
11
|
+
:gateways_config => File.dirname(__FILE__) + '/../../../recurring_billing/test/fixtures.yml',
|
12
|
+
:gateway => :paypal
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Checks if there are no exceptions while manipulating class with legit data; based on demo.rb
|
17
|
+
def test_crud_is_working
|
18
|
+
options = {
|
19
|
+
:account_id => 'test_acc_id',
|
20
|
+
:account_country => 'US',
|
21
|
+
:account_state => 'CA',
|
22
|
+
:tariff_plan => 'solo_monthly',
|
23
|
+
:start_date => (Date.today + 1),
|
24
|
+
:quantity => 1,
|
25
|
+
:end_date => DateTime.new(2010, 12, 11)
|
26
|
+
}
|
27
|
+
credit_card = credit_card()
|
28
|
+
credit_card_2 = credit_card(4929838635250031, {:year => Time.now.year + 5})
|
29
|
+
credit_card_3 = credit_card(4929273971564532, {:year => Time.now.year + 3})
|
30
|
+
|
31
|
+
assert_raise StandardError do; @sm.get_active_profile(-1); end
|
32
|
+
|
33
|
+
subscription_id = @sm.subscribe(options)
|
34
|
+
assert_equal 'pending', Subscription.find_by_id(subscription_id).status
|
35
|
+
assert_raise StandardError do; @sm.get_active_profile(subscription_id); end
|
36
|
+
@sm.pay_for_subscription(subscription_id, credit_card, {})
|
37
|
+
subscription = Subscription.find_by_id(subscription_id)
|
38
|
+
assert_equal 'ok', subscription.status
|
39
|
+
assert_equal 700, subscription.net_amount
|
40
|
+
assert_equal 140, subscription.taxes_amount
|
41
|
+
assert_equal 840, subscription.billing_amount
|
42
|
+
|
43
|
+
assert_equal 1, subscription.recurring_payment_profiles.length
|
44
|
+
profile = subscription.recurring_payment_profiles[0]
|
45
|
+
assert_equal 700, profile.net_amount
|
46
|
+
assert_equal 140, profile.taxes_amount
|
47
|
+
assert_equal 840, profile.amount
|
48
|
+
|
49
|
+
# create payment and check invoice
|
50
|
+
time = DateTime.now
|
51
|
+
transaction = Transaction.new({
|
52
|
+
:recurring_payment_profile_id => profile.id,
|
53
|
+
:gateway_reference => 'ABC0123456789XYZ',
|
54
|
+
:currency => 'USD',
|
55
|
+
:amount => 840,
|
56
|
+
:created_at => time
|
57
|
+
})
|
58
|
+
transaction.save!
|
59
|
+
|
60
|
+
invoice_data = @sm.get_invoice_data(transaction.id)
|
61
|
+
invoice_data[:date] = invoice_data[:date].strftime('%Y-%m-%d')
|
62
|
+
|
63
|
+
assert_equal({:taxes_comment =>"resident, CA",
|
64
|
+
:net_amount =>"7.00 USD",
|
65
|
+
:billing_account =>"test_acc_id",
|
66
|
+
:transaction_gateway=>"PAYPAL",
|
67
|
+
:taxes_amount =>"1.40 USD",
|
68
|
+
:transaction_id =>"ABC0123456789XYZ",
|
69
|
+
:number => transaction.id,
|
70
|
+
:date => time.strftime('%Y-%m-%d'),
|
71
|
+
:transaction_amount=>"8.40 USD",
|
72
|
+
:total_amount =>"8.40 USD",
|
73
|
+
:service_name =>"Solo (per month)"
|
74
|
+
},
|
75
|
+
invoice_data
|
76
|
+
)
|
77
|
+
|
78
|
+
transaction = Transaction.new({
|
79
|
+
:recurring_payment_profile_id => profile.id,
|
80
|
+
:gateway_reference => 'CAB0123456789ZYX',
|
81
|
+
:currency => 'CAD',
|
82
|
+
:amount => 840,
|
83
|
+
:created_at => Date.today
|
84
|
+
})
|
85
|
+
transaction.save!
|
86
|
+
assert_raises NotImplementedError do; @sm.get_invoice_data(transaction.id); end
|
87
|
+
|
88
|
+
transaction = Transaction.new({
|
89
|
+
:recurring_payment_profile_id => profile.id,
|
90
|
+
:gateway_reference => 'CAB0123456789ZYX',
|
91
|
+
:currency => 'USD',
|
92
|
+
:amount => 839,
|
93
|
+
:created_at => Date.today
|
94
|
+
})
|
95
|
+
transaction.save!
|
96
|
+
assert_raises NotImplementedError do; @sm.get_invoice_data(transaction.id); end
|
97
|
+
|
98
|
+
features = @sm.get_features(subscription_id)
|
99
|
+
|
100
|
+
options = {:card=>credit_card_2}
|
101
|
+
assert @sm.update_possible?(subscription_id, options)
|
102
|
+
@sm.update_subscription(subscription_id, options)
|
103
|
+
|
104
|
+
options = {:card=>credit_card_3, :start_date => Date.today + 42}
|
105
|
+
assert !@sm.update_possible?(subscription_id, options)
|
106
|
+
@sm.update_subscription(subscription_id, options)
|
107
|
+
|
108
|
+
@sm.unsubscribe(subscription_id)
|
109
|
+
assert_equal 'canceled', Subscription.find_by_id(subscription_id).status
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'activesupport'
|
6
|
+
|
7
|
+
silence_warnings do
|
8
|
+
require 'active_merchant'
|
9
|
+
end
|
10
|
+
|
11
|
+
require File.dirname(__FILE__) + "/connection"
|
12
|
+
require File.dirname(__FILE__) + '/../subscription_management'
|
13
|
+
|
14
|
+
# Turn off invalid certificate crashes
|
15
|
+
require 'openssl'
|
16
|
+
silence_warnings do
|
17
|
+
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveMerchant::Billing::Base.mode = :test
|
21
|
+
|
22
|
+
module Test
|
23
|
+
module Unit
|
24
|
+
class TestCase
|
25
|
+
|
26
|
+
|
27
|
+
DEFAULT_CREDENTIALS = File.dirname(__FILE__) + '/fixtures.yml'
|
28
|
+
|
29
|
+
private
|
30
|
+
def credit_card(number = '4242424242424242', options = {})
|
31
|
+
defaults = {
|
32
|
+
:number => number,
|
33
|
+
:month => 9,
|
34
|
+
:year => Time.now.year + 1,
|
35
|
+
:first_name => 'John',
|
36
|
+
:last_name => 'Doe',
|
37
|
+
:verification_value => '123',
|
38
|
+
:type => 'visa'
|
39
|
+
}.update(options)
|
40
|
+
|
41
|
+
ActiveMerchant::Billing::CreditCard.new(defaults)
|
42
|
+
end
|
43
|
+
|
44
|
+
def address(options = {})
|
45
|
+
{
|
46
|
+
:name => 'John Doe',
|
47
|
+
:address1 => '1234 My Street',
|
48
|
+
:address2 => 'Apt 1',
|
49
|
+
:company => 'Widgets Inc',
|
50
|
+
:city => 'Ottawa',
|
51
|
+
:state => 'ON',
|
52
|
+
:zip => 'K1C2N6',
|
53
|
+
:country => 'CA',
|
54
|
+
:phone => '(555)555-5555'
|
55
|
+
}.update(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def all_fixtures
|
59
|
+
@@fixtures ||= load_fixtures
|
60
|
+
end
|
61
|
+
|
62
|
+
def fixtures(key)
|
63
|
+
data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
|
64
|
+
|
65
|
+
data.dup
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_fixtures
|
69
|
+
file = DEFAULT_CREDENTIALS
|
70
|
+
yaml_data = YAML.load(File.read(file))
|
71
|
+
symbolize_keys(yaml_data)
|
72
|
+
|
73
|
+
yaml_data
|
74
|
+
end
|
75
|
+
|
76
|
+
def symbolize_keys(hash)
|
77
|
+
return unless hash.is_a?(Hash)
|
78
|
+
|
79
|
+
hash.symbolize_keys!
|
80
|
+
hash.each{|k,v| symbolize_keys(v)}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|