simplificator-ruby-kiva 0.1.0 → 0.2.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/README.rdoc +17 -1
- data/VERSION +1 -1
- data/lib/ruby-kiva/api.rb +45 -8
- data/lib/ruby-kiva/dynamic_initializer.rb +13 -9
- data/lib/ruby-kiva/journal_entry.rb +15 -3
- data/lib/ruby-kiva/lender.rb +23 -5
- data/lib/ruby-kiva/lending_action.rb +5 -1
- data/lib/ruby-kiva/loan.rb +36 -13
- data/lib/ruby-kiva/partner.rb +2 -1
- data/lib/ruby-kiva/payment.rb +3 -1
- data/lib/ruby-kiva/team.rb +24 -2
- data/lib/simplificator-ruby-kiva.rb +1 -1
- data/simplificator-ruby-kiva.gemspec +1 -1
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -4,7 +4,23 @@
|
|
4
4
|
This is a ruby wrapper for the kiva.org api.
|
5
5
|
See build.kiva.org for details.
|
6
6
|
|
7
|
-
==
|
7
|
+
== Status
|
8
|
+
|
9
|
+
Still work in progress, some tests are missing, documentation is quite weak.
|
10
|
+
Most API calls from Kiva are reflected.
|
11
|
+
http://build.kiva.org/api offers a list of API methods, not implemented: Methods, Release, Templates
|
12
|
+
|
13
|
+
== Attention
|
14
|
+
|
15
|
+
Whenever the unknown elements are encountered in the JSON documents, then an exception is raised.
|
16
|
+
Let me know if this happens and i will add the missing attributes. Or set Kiva::Api.friendly = true AND let me know.
|
17
|
+
|
18
|
+
|
19
|
+
== History
|
20
|
+
0.2.0 Updated API to include more functionality, added some tests
|
21
|
+
0.1.0 Initial Release
|
22
|
+
|
23
|
+
== Howto
|
8
24
|
|
9
25
|
include Kiva
|
10
26
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/ruby-kiva/api.rb
CHANGED
@@ -1,15 +1,49 @@
|
|
1
1
|
module Kiva
|
2
2
|
module Api
|
3
|
+
# set the API id
|
3
4
|
def self.app_id=(value)
|
4
5
|
@@app_id = value
|
5
6
|
end
|
7
|
+
# retrieve the API id
|
6
8
|
def self.app_id
|
7
|
-
@@app_id
|
9
|
+
@@app_id if defined? @@app_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.friendly=(value)
|
13
|
+
@@friendly = value
|
14
|
+
end
|
15
|
+
def self.friendly
|
16
|
+
@@friendly if defined? @@friendly
|
8
17
|
end
|
9
18
|
|
10
19
|
|
11
20
|
module ClassMethods
|
12
21
|
private
|
22
|
+
# map options to a new hash
|
23
|
+
# options
|
24
|
+
# mappings, an Array with up to 4 elements: [:source_key, :destination_key, sanitize (true, false), valid items]
|
25
|
+
# if mapping size is 1, then items are just copied over to new hash using same key
|
26
|
+
# if mapping size is 2, then items are copied over using :destination_key as the new key
|
27
|
+
# if mapping size is 3, then value is sanitized if mappind[2]
|
28
|
+
# if mapping size is 4, then value is verified to be included in mapping[3]
|
29
|
+
#
|
30
|
+
# if the value is nil in the options hash, then it is not copied
|
31
|
+
def map_options(options, mappings)
|
32
|
+
result = {}
|
33
|
+
mappings.each do |mapping|
|
34
|
+
if options.has_key?(mapping[0])
|
35
|
+
value = options[mapping[0]]
|
36
|
+
raise "Invalid value for #{mapping[0]}: #{value}" if mapping[3] && !mapping[3].include?(value)
|
37
|
+
result[mapping[1] || mapping[0]] = mapping[2] ? sanitize_id_parameter(value) : value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
# converts JSON to a PagedArray or a single Instance of a ruby-kiva Api class
|
44
|
+
# data: the JSON Date
|
45
|
+
# data_key, the key under which the date for a item is stored
|
46
|
+
# many if true: create an array / if false: create a single instance
|
13
47
|
def json_to_paged_array(data, data_key, many)
|
14
48
|
if many
|
15
49
|
if data[data_key]
|
@@ -26,20 +60,23 @@ module Kiva
|
|
26
60
|
end
|
27
61
|
end
|
28
62
|
|
63
|
+
# basic options
|
64
|
+
# includes App ID if set and adds pagination options if required
|
29
65
|
def base_options(options = {})
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
pagination_options(options)
|
34
|
-
end
|
66
|
+
result = pagination_options(options)
|
67
|
+
result[:app_id] = Api.app_id if Api.app_id
|
68
|
+
result
|
35
69
|
end
|
36
70
|
|
71
|
+
# builds a new hash with pagination options
|
37
72
|
def pagination_options(options = {})
|
38
|
-
{
|
73
|
+
options[:page] ? {:page => options[:page]} : {}
|
39
74
|
end
|
40
75
|
|
76
|
+
# sanitizes ID parameters for use in path of service
|
77
|
+
# pass a String or an Array with IDs, returns a comman separated String of IDs, whitespaces removed
|
41
78
|
def sanitize_id_parameter(id)
|
42
|
-
Array(id).join(',').gsub(/\s/, '')
|
79
|
+
Array(id).flatten.join(',').gsub(/\s/, '')
|
43
80
|
end
|
44
81
|
end
|
45
82
|
|
@@ -2,22 +2,26 @@ module Kiva
|
|
2
2
|
module DynamicInitializer
|
3
3
|
module ClassMethods
|
4
4
|
def typed_attr_accessor(name, klass, factory_method = :new, array = false)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
instance_variable_set("@#{name}", typed)
|
5
|
+
define_method("#{name}=") do |value|
|
6
|
+
if array
|
7
|
+
typed = value.map() {|item| klass.send(factory_method, item)}
|
8
|
+
else
|
9
|
+
typed = klass.send(factory_method, value)
|
12
10
|
end
|
13
|
-
|
11
|
+
instance_variable_set("@#{name}", typed)
|
12
|
+
end
|
13
|
+
attr_reader name
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
module InstanceMethods
|
18
18
|
def initialize(options = {})
|
19
19
|
options.each do |key, value|
|
20
|
-
|
20
|
+
if respond_to?("#{key}=")
|
21
|
+
self.send("#{key}=", value)
|
22
|
+
elsif !Api.friendly
|
23
|
+
raise "Attribute #{key} is not yet supported. Set Api.friendly = true"
|
24
|
+
end
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
@@ -5,6 +5,8 @@ module Kiva
|
|
5
5
|
attr_accessor :id, :body, :subject, :author, :bulk, :comment_count, :recommendation_count
|
6
6
|
|
7
7
|
typed_attr_accessor :date, Time, :parse
|
8
|
+
typed_attr_accessor :image, Kiva::Image
|
9
|
+
typed_attr_accessor :video, Kiva::Video
|
8
10
|
|
9
11
|
def bulk?
|
10
12
|
self.bulk
|
@@ -13,7 +15,10 @@ module Kiva
|
|
13
15
|
def self.find(params)
|
14
16
|
if params[:loan_id]
|
15
17
|
json_to_paged_array(get("/loans/#{params[:loan_id]}/journal_entries.json",
|
16
|
-
:query =>
|
18
|
+
:query => sanitize_options(params)), 'journal_entries', true)
|
19
|
+
else
|
20
|
+
json_to_paged_array(get("/journal_entries/search.json",
|
21
|
+
:query => sanitize_options(params)), 'journal_entries', true)
|
17
22
|
end
|
18
23
|
end
|
19
24
|
|
@@ -23,10 +28,17 @@ module Kiva
|
|
23
28
|
|
24
29
|
private
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
OPTION_MAPPINGS = [
|
32
|
+
[:media, :media, false, ['any', 'video', 'image']],
|
33
|
+
[:sort_by, :sort_by, false, ['newest', 'oldest', 'recommendation_count', 'comment_count']],
|
34
|
+
[:partner_id, :partner, true],
|
35
|
+
[:query, :q]
|
36
|
+
]
|
37
|
+
def self.sanitize_options(options = {})
|
38
|
+
result = base_options(options).merge(map_options(options, OPTION_MAPPINGS))
|
28
39
|
result['include_bulk'] = options[:include_bulk] ? 1 : 0
|
29
40
|
result
|
30
41
|
end
|
42
|
+
|
31
43
|
end
|
32
44
|
end
|
data/lib/ruby-kiva/lender.rb
CHANGED
@@ -24,30 +24,48 @@ module Kiva
|
|
24
24
|
"<Lender #{self.lender_id}>"
|
25
25
|
end
|
26
26
|
|
27
|
+
def self.newest(params = {})
|
28
|
+
json_to_paged_array(get('/lenders/newest.json', :query => sanitize_options(params)), 'lenders', true)
|
29
|
+
end
|
30
|
+
|
27
31
|
# Find Lenders
|
28
32
|
# __either__
|
29
33
|
# :id : A single ID or a comma Separated String of IDs or an Array of IDs
|
30
34
|
# __or__
|
31
35
|
# :loan_id : A single loan ID
|
32
36
|
# __or__
|
33
|
-
# :team_id : a single team ID
|
37
|
+
# :team_id : a single team ID, supports :sort_by
|
34
38
|
#
|
35
39
|
# If searching for a single ID, then this method can return nil (no item with this ID found).
|
36
40
|
# Otherwise this method will always return a PagedArray instance (which might be empty though)
|
37
41
|
# If querying for multiple items, then :page is supported
|
38
|
-
def self.find(params)
|
42
|
+
def self.find(params = {})
|
39
43
|
if params[:id] # find one or many by lender ID
|
40
|
-
data = get("/lenders/#{sanitize_id_parameter(params[:id])}.json", :query =>
|
44
|
+
data = get("/lenders/#{sanitize_id_parameter(params[:id])}.json", :query => sanitize_options(params))
|
41
45
|
many = sanitize_id_parameter(params[:id]).include?(',')
|
42
46
|
elsif params[:loan_id] # find lenders for a loan
|
43
|
-
data = get("/loans/#{params[:loan_id]}/lenders.json", :query =>
|
47
|
+
data = get("/loans/#{params[:loan_id]}/lenders.json", :query => sanitize_options(params))
|
44
48
|
many = true
|
45
49
|
elsif params[:team_id]
|
46
|
-
data = get("/teams/#{params[:team_id]}/lenders.json", :query =>
|
50
|
+
data = get("/teams/#{params[:team_id]}/lenders.json", :query => sanitize_options(params))
|
51
|
+
many = true
|
52
|
+
else
|
53
|
+
data = get("/lenders/search.json", :query => sanitize_options(params))
|
47
54
|
many = true
|
48
55
|
end
|
49
56
|
json_to_paged_array(data, 'lenders', many)
|
50
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
OPTION_MAPPINGS = [
|
61
|
+
[:sort_by, :sort_by, false, ['oldest', 'newest']],
|
62
|
+
[:occupation],
|
63
|
+
[:query, :q]
|
64
|
+
]
|
65
|
+
def self.sanitize_options(options = {})
|
66
|
+
base_options(options).merge(map_options(options, OPTION_MAPPINGS))
|
67
|
+
end
|
68
|
+
|
51
69
|
end
|
52
70
|
end
|
53
71
|
|
@@ -10,9 +10,13 @@ module Kiva
|
|
10
10
|
typed_attr_accessor :loan, Kiva::Loan
|
11
11
|
|
12
12
|
|
13
|
-
def self.
|
13
|
+
def self.newest(options = {})
|
14
14
|
json_to_paged_array(get('/lending_actions/recent.json'), 'lending_actions', true)
|
15
15
|
end
|
16
|
+
# renamed from recent to 'newest' to make it consistent with LendingAction and Lender
|
17
|
+
class <<self
|
18
|
+
alias_method :recent, :newest
|
19
|
+
end
|
16
20
|
|
17
21
|
end
|
18
22
|
end
|
data/lib/ruby-kiva/loan.rb
CHANGED
@@ -13,7 +13,9 @@ module Kiva
|
|
13
13
|
typed_attr_accessor :video, Kiva::Video
|
14
14
|
typed_attr_accessor :terms, Kiva::Terms
|
15
15
|
typed_attr_accessor :posted_date, Date, :parse
|
16
|
+
typed_attr_accessor :paid_date, Date, :parse
|
16
17
|
typed_attr_accessor :borrowers, Kiva::Borrower, :new, true
|
18
|
+
typed_attr_accessor :payments, Kiva::Payment, :new, true
|
17
19
|
|
18
20
|
# description consists of available languages and texts in different languages
|
19
21
|
# texts are only available when doing a find by id
|
@@ -46,10 +48,14 @@ module Kiva
|
|
46
48
|
@journal_entries ||= JournalEntry.find(params.merge({:loan_id => self.id}))
|
47
49
|
end
|
48
50
|
|
51
|
+
def loan_updates
|
52
|
+
@loan_updates ||= find_loan_updates()
|
53
|
+
end
|
54
|
+
|
49
55
|
|
50
56
|
# Supported options:
|
51
57
|
# * :page: The requested page number
|
52
|
-
def self.
|
58
|
+
def self.newest(options = {})
|
53
59
|
data = get('/loans/newest.json', :query => base_options(options))
|
54
60
|
json_to_paged_array(data, 'loans', true)
|
55
61
|
end
|
@@ -73,35 +79,52 @@ module Kiva
|
|
73
79
|
# When searching for multiple Loans, then the :page parameter is supported to specify the desired page.
|
74
80
|
def self.find(params)
|
75
81
|
if params[:id] # find one or many by ID
|
76
|
-
data = get("/loans/#{sanitize_id_parameter(params[:id])}.json", :query =>
|
82
|
+
data = get("/loans/#{sanitize_id_parameter(params[:id])}.json", :query => sanitize_options(params))
|
77
83
|
many = sanitize_id_parameter(params[:id]).include?(',')
|
78
84
|
elsif params[:lender_id] # find all loans for a lender
|
79
|
-
data = get("/lenders/#{params[:lender_id]}/loans.json", :query =>
|
85
|
+
data = get("/lenders/#{params[:lender_id]}/loans.json", :query => sanitize_options(params))
|
80
86
|
many = true
|
81
87
|
elsif params[:team_id] # find all loans for a team
|
82
|
-
data = get("/teams/#{params[:team_id]}/loans.json", :query =>
|
88
|
+
data = get("/teams/#{params[:team_id]}/loans.json", :query => sanitize_options(params))
|
83
89
|
many = true
|
84
90
|
else # search
|
85
|
-
|
91
|
+
puts "Searching with #{base_options(params).merge(find_options(params)).inspect}"
|
92
|
+
data = get('/loans/search.json', :query => sanitize_options(params))
|
86
93
|
many = true
|
87
94
|
end
|
88
95
|
json_to_paged_array(data, 'loans', many)
|
89
96
|
end
|
90
97
|
|
91
98
|
def to_s()
|
92
|
-
"<Loan '%s' (%s) in %s with status %s, from %s>" % [self.name, self.id, self.location, self.
|
99
|
+
"<Loan '%s' (%s) in %s with status %s, from %s>" % [self.name, self.id, self.location, self.id, self.borrowers]
|
93
100
|
end
|
94
101
|
|
95
102
|
private
|
96
103
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
104
|
+
def find_loan_updates
|
105
|
+
data = Loan.get("/loans/#{self.id}/updates.json")
|
106
|
+
data['loan_updates'].map do |entry|
|
107
|
+
type = entry.delete('update_type')
|
108
|
+
case type
|
109
|
+
when 'journal_entry' then JournalEntry.new(entry['journal_entry'])
|
110
|
+
when 'payment' then Payment.new(entry['payment'])
|
111
|
+
else raise "unknown type #{type}"
|
112
|
+
end
|
101
113
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
114
|
+
end
|
115
|
+
|
116
|
+
OPTION_MAPPINGS = [
|
117
|
+
[:partner_id, :partner, true],
|
118
|
+
[:sort_by, :sort_by, false, ['oldest', 'newest']],
|
119
|
+
[:status, :status, false, ['fundraising', 'funded', 'in_repayment', 'paid', 'defaulted']],
|
120
|
+
[:query, :q],
|
121
|
+
[:gender, :gender, false, ['male', 'female']],
|
122
|
+
[:region, :region, false, ['na', 'ca', 'sa', 'af', 'as', 'me', 'ee']],
|
123
|
+
[:sector],
|
124
|
+
[:country_code],
|
125
|
+
]
|
126
|
+
def self.sanitize_options(options = {})
|
127
|
+
base_options(options).merge(map_options(options, OPTION_MAPPINGS))
|
105
128
|
end
|
106
129
|
|
107
130
|
|
data/lib/ruby-kiva/partner.rb
CHANGED
@@ -9,8 +9,9 @@ module Kiva
|
|
9
9
|
|
10
10
|
# Find a partner
|
11
11
|
# either by :id or all of them
|
12
|
-
# Since kiva does not offer
|
12
|
+
# Since kiva does not offer search,
|
13
13
|
# finding by id is implemented in memory/ruby.
|
14
|
+
# Pagination is not supported, page size is 200 and currently there are 143 partners
|
14
15
|
# Items are cached but can be reloaded by passing :reload => true (caching is suggested by kiva...)
|
15
16
|
def self.find(params = {})
|
16
17
|
if params[:id]
|
data/lib/ruby-kiva/payment.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
module Kiva
|
2
2
|
class Payment
|
3
3
|
include DynamicInitializer
|
4
|
-
attr_accessor :amount
|
4
|
+
attr_accessor :amount, :local_amount, :rounded_local_amount, :comment, :payment_id
|
5
5
|
typed_attr_accessor :due_date, Time, :parse
|
6
|
+
typed_attr_accessor :settlement_date, Time, :parse
|
7
|
+
typed_attr_accessor :processed_date, Time, :parse
|
6
8
|
|
7
9
|
def to_s
|
8
10
|
"<Payment due at #{self.due_date} : #{self.amount}>"
|
data/lib/ruby-kiva/team.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Kiva
|
2
2
|
class Team
|
3
|
+
|
3
4
|
include DynamicInitializer
|
4
5
|
include Api
|
5
6
|
|
@@ -19,10 +20,31 @@ module Kiva
|
|
19
20
|
# find a team by :id or :shortname
|
20
21
|
def self.find(params)
|
21
22
|
if params[:id]
|
22
|
-
|
23
|
+
data = get("/teams/#{sanitize_id_parameter(params[:id])}.json", :query => sanitize_options(params))
|
24
|
+
many = sanitize_id_parameter(params[:id]).include?(',')
|
23
25
|
elsif params[:shortname]
|
24
|
-
|
26
|
+
data = get("/teams/using_shortname/#{sanitize_id_parameter(params[:shortname])}.json", :query => sanitize_options(params))
|
27
|
+
many = sanitize_id_parameter(params[:shortnames]).include?(',')
|
28
|
+
else
|
29
|
+
data = get("/teams/search.json", :query => sanitize_options(params))
|
30
|
+
many = true
|
25
31
|
end
|
32
|
+
json_to_paged_array(data, 'teams', many)
|
26
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
OPTION_MAPPINGS = [
|
38
|
+
[:sort_by, :sort_by, false, ['oldest', 'newest']],
|
39
|
+
[:occupation],
|
40
|
+
[:query, :q],
|
41
|
+
[:country_code],
|
42
|
+
[:membership_type, :membership_type, false, ['open', 'closed']],
|
43
|
+
[:category, :category, false, ['Alumni Groups', 'Businesses', 'Businesses - Internal Groups', 'Clubs', 'Colleges/Universities', 'Common Interest', 'Events', 'Families', 'Field Partner Fans', 'Friends', 'Local Area', 'Memorials', 'Religious Congregations', 'Schools', 'Sports Groups', 'Youth Groups', 'Other']],
|
44
|
+
]
|
45
|
+
def self.sanitize_options(options = {})
|
46
|
+
base_options(options).merge(map_options(options, OPTION_MAPPINGS))
|
47
|
+
end
|
48
|
+
|
27
49
|
end
|
28
50
|
end
|