musoni_ruby 0.0.01
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +10 -0
- data/.travis.yml +13 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Guardfile +50 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +20 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/musoni-ruby.rb +1 -0
- data/lib/musoni_ruby/configuration.rb +16 -0
- data/lib/musoni_ruby/endpoints/_endpoint.rb +101 -0
- data/lib/musoni_ruby/endpoints/client.rb +91 -0
- data/lib/musoni_ruby/endpoints/datatable.rb +77 -0
- data/lib/musoni_ruby/endpoints/loan.rb +78 -0
- data/lib/musoni_ruby/endpoints/run_report.rb +21 -0
- data/lib/musoni_ruby/endpoints/savings_account.rb +77 -0
- data/lib/musoni_ruby/fetch.rb +53 -0
- data/lib/musoni_ruby/support/fake_musoni/authentication/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni/clients/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni/datatables/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni/loans/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni/runreports/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni/savingsaccounts/.keep +0 -0
- data/lib/musoni_ruby/support/fake_musoni.rb +25 -0
- data/lib/musoni_ruby/support/test_helper.rb +173 -0
- data/lib/musoni_ruby/version.rb +3 -0
- data/lib/musoni_ruby.rb +54 -0
- data/musoni_ruby.gemspec +47 -0
- metadata +285 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
module Musoni
|
2
|
+
class SavingsAccount < Musoni::Endpoint
|
3
|
+
attr_writer :transactions, :payable_items
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Musoni::SavingsAccount.all()
|
8
|
+
def all(offset:1,limit:100)
|
9
|
+
url = "/savingsaccounts"
|
10
|
+
Musoni::Fetch.get(url,query:{offset:offset,limit:limit}).pageItems
|
11
|
+
end
|
12
|
+
|
13
|
+
# Musoni::SavingsAccount.find(savingsaccount_id)
|
14
|
+
def find(savingsaccount_id,fetch:true)
|
15
|
+
url = "/savingsaccounts/#{savingsaccount_id}?associations=all"
|
16
|
+
response = Musoni::Fetch.get(url) if fetch
|
17
|
+
savingsaccount = new(id:savingsaccount_id,response:response)
|
18
|
+
end
|
19
|
+
|
20
|
+
# account_attributes = {:clientId=>"1",:productId=>"1",:submittedOnDate=>"13-05-2015",:fieldOfficerId=>"1",:charges=>[],:allowOverdraft=>false}
|
21
|
+
# Musoni::SavingsAccount.create(account_attributes)
|
22
|
+
def create(options={})
|
23
|
+
url = "/savingsaccounts"
|
24
|
+
response = Musoni::Fetch.post(url,options)
|
25
|
+
new(options.merge!(id:response.savingsId ,response:response)) rescue response
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# # date = {:approvedOnDate=>"13-05-2015"}
|
31
|
+
# # account.activate(date)
|
32
|
+
%w{approve activate}.each do |m|
|
33
|
+
define_method m do |options={}|
|
34
|
+
options[:"#{m}dOnDate"] ||= Time.now.strftime("%d-%m-%Y")
|
35
|
+
url = "/savingsaccounts/#{self.id}?command=#{m}"
|
36
|
+
response = Musoni::Fetch.post(url,options)
|
37
|
+
new(options.merge!(id:response.savingsId ,response:response)) rescue response
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# transaction = {:transactionDate=>"15-05-2015",:transactionAmount=>"100",:receiptNumber=>"ABC",:paymentTypeId=>"177"}
|
42
|
+
# # account.activate(date)
|
43
|
+
%w{deposit withdrawal}.each do |m|
|
44
|
+
define_method m do |options={}|
|
45
|
+
options[:transactionDate] ||= Time.now.strftime("%d-%m-%Y")
|
46
|
+
url = "/savingsaccounts/#{self.id}/transactions?command=#{m}"
|
47
|
+
response = Musoni::Fetch.post(url,options)
|
48
|
+
new(options.merge!(id:response.savingsId ,response:response)) rescue response
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# # savingsaccount.update(name:new_name)
|
53
|
+
# def update(options)
|
54
|
+
# url = "/savingsaccounts/#{self.id}"
|
55
|
+
# response = Musoni::Fetch.put(url,options)
|
56
|
+
# self.response = response
|
57
|
+
# end
|
58
|
+
|
59
|
+
|
60
|
+
# # Musoni::SavingsAccount.find(26, fetch:false).transactions(offset:1,limit:100)
|
61
|
+
# def transactions(offset:1,limit:100)
|
62
|
+
# find_all(offset:offset,limit:limit)
|
63
|
+
# end
|
64
|
+
|
65
|
+
# # Musoni::SavingsAccount.find(26, fetch:false).payable_items(offset:1,limit:100)
|
66
|
+
# def payable_items(offset:1,limit:100)
|
67
|
+
# find_all(offset:offset,limit:limit)
|
68
|
+
# end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def after_initialize
|
73
|
+
@endpoint = 'savingsaccounts'
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Musoni
|
2
|
+
class Fetch
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
base_uri "https://demo.musonisystem.com:8443/api/v1"
|
6
|
+
parser proc {|data| Hashie::Mash.new(response: (JSON.parse(data) rescue {data:data}.to_json) ).response}
|
7
|
+
format :json
|
8
|
+
headers
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def headers
|
12
|
+
Musoni.configuration.header.merge!(super)
|
13
|
+
end
|
14
|
+
|
15
|
+
%w(get put post delete).each do |m|
|
16
|
+
define_method m do |path, options={}, &block|
|
17
|
+
# body = date_parameters(options).merge!(options)
|
18
|
+
options = {body: date_parameters(options).merge!(options).to_json}
|
19
|
+
|
20
|
+
res = perform_request Net::HTTP::Put, path, options, &block if m == 'put'
|
21
|
+
res = perform_request Net::HTTP::Get, path, options, &block if m == 'get'
|
22
|
+
res = perform_request Net::HTTP::Post, path, options, &block if m == 'post'
|
23
|
+
res = perform_request Net::HTTP::Delete, path, options, &block if m == 'delete'
|
24
|
+
save_json(res) if load_json?
|
25
|
+
res
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def save_json(response)
|
30
|
+
request_method = response.request.http_method.name.split('::').last.upcase
|
31
|
+
file_path = response.request.path.to_s
|
32
|
+
slash,model,*file_name = file_path.split('?')[0].split(/\/|\?/)
|
33
|
+
file_location = "lib/musoni_ruby/support/fake_musoni/#{model}/#{request_method}_#{file_name.join('_')}.json"
|
34
|
+
File.write(file_location, response.body)
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_json?
|
38
|
+
# load JSON if WebMock is off while testing and only in local env with load musoni turned on
|
39
|
+
defined?(WebMock).nil? and ENV['CI_TEST'].nil? and defined?(Minitest) and ENV['LOAD_MUSONI'] == "true"
|
40
|
+
end
|
41
|
+
|
42
|
+
def date_parameters(options)
|
43
|
+
# bp
|
44
|
+
if options.map{|k,v| k.to_s }.grep(/Date/).any?
|
45
|
+
{dateFormat:"dd-MM-yyyy", locale:"en_GB"}
|
46
|
+
else
|
47
|
+
{}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'tilt/erb'
|
3
|
+
|
4
|
+
class FakeMusoni < Sinatra::Base
|
5
|
+
|
6
|
+
[ :get, :post, :put, :delete ].each do |method|
|
7
|
+
send method, /.*/ do
|
8
|
+
# if (request.env['HTTP_X_WSSE'].empty? rescue true)
|
9
|
+
# [200, {}, [{base:["Authentication Failed"]}.to_json]]
|
10
|
+
# else
|
11
|
+
slash,api,v,model,*path = request.path_info.split('?')[0].split(/\/|\?/)
|
12
|
+
json_response 200, "#{model}/#{request.request_method}_#{path.join('_')}.json"
|
13
|
+
# end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def json_response(response_code, file_name)
|
20
|
+
content_type :json
|
21
|
+
status response_code
|
22
|
+
headers "content-type"=>["application/json; charset=utf-8"]
|
23
|
+
erb File.open(File.dirname(__FILE__) + '/fake_musoni/' + file_name, 'rb').read
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Musoni::TestHelper
|
2
|
+
def create_musoni_client
|
3
|
+
client_attributes = {:officeId=>"2",
|
4
|
+
:firstname=> Faker::Name.first_name,
|
5
|
+
:staffId=>"1",
|
6
|
+
:lastname=> Faker::Name.last_name,
|
7
|
+
:middlename=> Faker::Name.first_name,
|
8
|
+
:externalId=>rand(100000),
|
9
|
+
:mobileNo=>"07234#{rand(10000)}",
|
10
|
+
:submittedOnDate=>"11-05-2015",
|
11
|
+
:active=>"true",
|
12
|
+
:activationDate=> Time.now.strftime("%d-%m-%Y")
|
13
|
+
}
|
14
|
+
@@musoni_client ||= Musoni::Client.create(client_attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_musoni_loan
|
18
|
+
loan_options = {
|
19
|
+
:submittedOnDate=>"13-05-2015",
|
20
|
+
:clientId=>"3",
|
21
|
+
:productId=>"1",
|
22
|
+
:loanOfficerId=>"1",
|
23
|
+
:loanPurposeId=>"37",
|
24
|
+
:principal=>"10,000.00",
|
25
|
+
:loanTermFrequency=>"1",
|
26
|
+
:loanTermFrequencyType=>"2",
|
27
|
+
:numberOfRepayments=>"1",
|
28
|
+
:repaymentEvery=>"1",
|
29
|
+
:repaymentFrequencyType=>"2",
|
30
|
+
:transactionProcessingStrategyId=>"1",
|
31
|
+
:interestRatePerPeriod=>"5",
|
32
|
+
:expectedDisbursementDate=>"13-05-2015",
|
33
|
+
:amortizationType=>"1",
|
34
|
+
:interestType=>"1",
|
35
|
+
:interestCalculationPeriodType=>"1",
|
36
|
+
:inArrearsTolerance=>"0",
|
37
|
+
:interestChargedFromDate=>"13-05-2015",
|
38
|
+
:repaymentsStartingFromDate=>"13-06-2015",
|
39
|
+
:charges=>[],
|
40
|
+
:loanType=>"individual",
|
41
|
+
:linkAccountId=>"",
|
42
|
+
:graceOnPrincipalPayment=>"0",
|
43
|
+
:graceOnInterestCharged=>"0",
|
44
|
+
:graceOnInterestPayment=>"0",
|
45
|
+
:fundId=>"1",
|
46
|
+
:createStandingInstructionAtDisbursement=>false
|
47
|
+
}
|
48
|
+
@@musoni_loan ||= Musoni::Loan.create(loan_options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_musoni_savings_account
|
52
|
+
account_options = {
|
53
|
+
:clientId=>"1",
|
54
|
+
:productId=>"1",
|
55
|
+
:submittedOnDate=>"13-05-2015",
|
56
|
+
:fieldOfficerId=>"1",
|
57
|
+
:charges=>[],
|
58
|
+
:allowOverdraft=>false
|
59
|
+
}
|
60
|
+
@@musoni_savings_account ||= Musoni::SavingsAccount.create(account_options)
|
61
|
+
end
|
62
|
+
|
63
|
+
[
|
64
|
+
:ml_client_details,
|
65
|
+
:cct_Borrower_Details,
|
66
|
+
:cct_TransUnion,
|
67
|
+
:cct_First_Access_Score
|
68
|
+
]
|
69
|
+
|
70
|
+
|
71
|
+
def create_client_datatable
|
72
|
+
client = create_musoni_client
|
73
|
+
datatable_attributes = {
|
74
|
+
:MaritalStatus_cv_maritalStatus=>"Single",
|
75
|
+
:dateOfBirth=> Faker::Date.backward(10000).strftime("%d-%m-%Y"),
|
76
|
+
:Email=> Faker::Internet.email,
|
77
|
+
# :Password=> Faker::Internet.password,
|
78
|
+
:Client_Type=>"Lender",
|
79
|
+
:dateFormat=>"DD-MM-YYYY",
|
80
|
+
:locale=>"en_GB"
|
81
|
+
}
|
82
|
+
@@musoni_client_datatable ||= Musoni::Datatable.create(:ml_client_details,client.id,datatable_attributes)
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_borrower_datatable
|
86
|
+
client = create_musoni_client
|
87
|
+
datatable_attributes = {
|
88
|
+
:town=>"Nairobi",
|
89
|
+
:address=>"Waiyaki Way",
|
90
|
+
:MaritalStatus_cv_maritalStatus=>"Single",
|
91
|
+
:dateOfBirth=>"01-01-1900",
|
92
|
+
:state=>"state",
|
93
|
+
:E_mail_address=> Faker::Internet.email,
|
94
|
+
:Password=> Faker::Internet.password,
|
95
|
+
:Sector=>"Sector1",
|
96
|
+
:occupation=>"Something",
|
97
|
+
:children_present=>"yes",
|
98
|
+
:household_size=>"10",
|
99
|
+
:dependants_no=>"5",
|
100
|
+
:household_assets=>"None",
|
101
|
+
:monthly_expense_food=>"100",
|
102
|
+
:monthly_expense_housing=>"500",
|
103
|
+
:monthly_expense_school=>"150",
|
104
|
+
:monthly_expense_medical=>"200",
|
105
|
+
:monthly_expense_tranport=>"230",
|
106
|
+
:monthly_expense_health=>"320",
|
107
|
+
:business_ownership=>"Yes",
|
108
|
+
:business_experience=>"10",
|
109
|
+
:book_keeping=>"yes",
|
110
|
+
:monthly_reorder_level=>"10",
|
111
|
+
:current_inventory_level=>"10",
|
112
|
+
:active_savings_devices=>"m-shwari,something else,3rd option",
|
113
|
+
:savings_emergency=>"1001",
|
114
|
+
:savings_school=>"1001",
|
115
|
+
:savings_asset=>"100",
|
116
|
+
:savings_entertainment=>"200",
|
117
|
+
:savings_medical=>"400",
|
118
|
+
:savings_business=>"500",
|
119
|
+
:savings_other=>"100",
|
120
|
+
:credit_limit_mshwari=>"100000000",
|
121
|
+
:saving_frequency=>"None",
|
122
|
+
:remittance_amount=>"1000",
|
123
|
+
:remittance_location=>"Yaya",
|
124
|
+
:remittance_frequency=>"daily",
|
125
|
+
:mobile_use=>"yes",
|
126
|
+
:last_mmoney_out=>"today",
|
127
|
+
:last_mmoney_in=>"yesterday",
|
128
|
+
:phones_owned=>"10",
|
129
|
+
:language_use=>"English,Dutch",
|
130
|
+
:data_mpesa=>"Mledger BLOB",
|
131
|
+
:income_weekly=>10000,
|
132
|
+
:survey_id=>123,
|
133
|
+
:dateFormat=>"dd-MM-yyyy",
|
134
|
+
:locale=>"en_GB"
|
135
|
+
}
|
136
|
+
@@musoni_borrower_datatable ||= Musoni::Datatable.create(:cct_Borrower_Details,client.id,datatable_attributes)
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_transunion_datatable
|
140
|
+
client = create_musoni_client
|
141
|
+
datatable_attributes = {
|
142
|
+
:Credit_History=>"24",
|
143
|
+
:NPA_Accounts=>"1",
|
144
|
+
:NPA_Closed_Accounts=>"1",
|
145
|
+
:NPA_Open_Accounts=>"0",
|
146
|
+
:PA_Accounts=>"11",
|
147
|
+
:PA_Closed_Accounts=>"10",
|
148
|
+
:PA_Open_Accounts=>"1",
|
149
|
+
:Response_Statuscode=>"300",
|
150
|
+
:dateFormat=>"dd-MM-yyyy",
|
151
|
+
:locale=>"en_GB",
|
152
|
+
:submittedon_date=>"27-05-2015",
|
153
|
+
:submittedon_userid=>1
|
154
|
+
}
|
155
|
+
@@musoni_transunion_datatable ||= Musoni::Datatable.create(:cct_TransUnion,client.id,datatable_attributes)
|
156
|
+
end
|
157
|
+
|
158
|
+
def create_firstaccess_datatable
|
159
|
+
client = create_musoni_client
|
160
|
+
datatable_attributes = {
|
161
|
+
:Status=>"Approved",
|
162
|
+
:Risk_Bucket=>"Very Low",
|
163
|
+
:Loan_Size=>"10000",
|
164
|
+
:Interest_Rate=>"10.05",
|
165
|
+
:dateFormat=>"dd-MM-yyyy",
|
166
|
+
:locale=>"en_GB",
|
167
|
+
:submittedon_date=>"27-05-2015",
|
168
|
+
:submittedon_userid=>1
|
169
|
+
}
|
170
|
+
@@musoni_firstaccess_datatable ||= Musoni::Datatable.create(:cct_First_Access_Score,client.id,datatable_attributes)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
data/lib/musoni_ruby.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "hashie"
|
3
|
+
require "musoni_ruby/version"
|
4
|
+
require "musoni_ruby/configuration"
|
5
|
+
require "musoni_ruby/fetch"
|
6
|
+
require "musoni_ruby/endpoints/_endpoint"
|
7
|
+
require "musoni_ruby/endpoints/client"
|
8
|
+
require "musoni_ruby/endpoints/datatable"
|
9
|
+
require "musoni_ruby/endpoints/loan"
|
10
|
+
require "musoni_ruby/endpoints/run_report"
|
11
|
+
require "musoni_ruby/endpoints/savings_account"
|
12
|
+
|
13
|
+
# begin
|
14
|
+
# require "pry"
|
15
|
+
# require "pry-alias"
|
16
|
+
# rescue LoadError
|
17
|
+
# end
|
18
|
+
|
19
|
+
module Musoni
|
20
|
+
class << self
|
21
|
+
attr_writer :configuration
|
22
|
+
|
23
|
+
def configuration
|
24
|
+
@configuration ||= Configuration.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset
|
28
|
+
@configuration = Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup
|
32
|
+
yield(configuration)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Musoni.authenticate(user:'username',password:"98497927493")
|
36
|
+
def authenticate(user:nil,password:nil,tenant:nil)
|
37
|
+
# bp
|
38
|
+
url = "/authentication?username=#{user}&password=#{password}&tenantIdentifier=#{tenant}"
|
39
|
+
request = Musoni::Fetch.post(url)
|
40
|
+
if (request.authenticated rescue false)
|
41
|
+
@configuration = Configuration.new(tenant:tenant, token:request.base64EncodedAuthenticationKey)
|
42
|
+
# @configuration.tenant = tenant
|
43
|
+
# @configuration.token = request.base64EncodedAuthenticationKey
|
44
|
+
# Musoni.setup do |config|
|
45
|
+
# config.tenant = tenant
|
46
|
+
# config.token = request.base64EncodedAuthenticationKey
|
47
|
+
# end
|
48
|
+
end
|
49
|
+
request
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
data/musoni_ruby.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'musoni_ruby/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "musoni_ruby"
|
8
|
+
spec.version = Musoni::VERSION
|
9
|
+
spec.authors = ["Kariuki Gathitu"]
|
10
|
+
spec.email = ["kgathi2@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby Client for interfacing with Musoni systems API}
|
13
|
+
spec.description = %q{Railsesque may to integrate with Musoni systems}
|
14
|
+
spec.homepage = "https://bitbucket.org/kgathi2/musoni_ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
# else
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
spec.required_ruby_version = '~> 2.0'
|
30
|
+
|
31
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "guard", "~> 2.12"
|
34
|
+
spec.add_development_dependency "minitest", "~> 5.6"
|
35
|
+
spec.add_development_dependency "guard-minitest", "~> 2.4"
|
36
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.0"
|
37
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
38
|
+
spec.add_development_dependency "pry-nav", "~> 0.2"
|
39
|
+
spec.add_development_dependency "pry-alias", "~> 0.0"
|
40
|
+
spec.add_development_dependency "coveralls", '~> 0.8'
|
41
|
+
spec.add_development_dependency "webmock", '~> 1.21'
|
42
|
+
spec.add_development_dependency "sinatra", '~> 1.4'
|
43
|
+
spec.add_development_dependency "faker", '~> 1.4'
|
44
|
+
|
45
|
+
spec.add_dependency 'httparty', "~> 0.13"
|
46
|
+
spec.add_dependency 'hashie', "~> 3.4"
|
47
|
+
end
|