fellowshipone-api 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +64 -0
  7. data/README.rdoc +44 -0
  8. data/Rakefile +32 -0
  9. data/fellowshipone_api.gemspec +25 -0
  10. data/lib/api/api_object.rb +141 -0
  11. data/lib/api/communication.rb +59 -0
  12. data/lib/api/contribution.rb +97 -0
  13. data/lib/api/contribution_list.rb +57 -0
  14. data/lib/api/fund.rb +40 -0
  15. data/lib/api/fund_list.rb +53 -0
  16. data/lib/api/household.rb +50 -0
  17. data/lib/api/household_list.rb +78 -0
  18. data/lib/api/member_household_list.rb +73 -0
  19. data/lib/api/mergeable_household_list.rb +79 -0
  20. data/lib/api/mergeable_person_list.rb +110 -0
  21. data/lib/api/person.rb +169 -0
  22. data/lib/api/person_list.rb +85 -0
  23. data/lib/api/search.rb +55 -0
  24. data/lib/auto_load.rb +17 -0
  25. data/lib/common.rb +76 -0
  26. data/lib/exceptions.rb +5 -0
  27. data/lib/fellowship_one.rb +54 -0
  28. data/lib/oauth_monkey_patch.rb +13 -0
  29. data/lib/readers/api_reader.rb +34 -0
  30. data/lib/readers/communication_reader.rb +19 -0
  31. data/lib/readers/contribution_list_reader.rb +37 -0
  32. data/lib/readers/contribution_reader.rb +18 -0
  33. data/lib/readers/fund_list_reader.rb +13 -0
  34. data/lib/readers/fund_reader.rb +14 -0
  35. data/lib/readers/household_list_reader.rb +62 -0
  36. data/lib/readers/household_reader.rb +18 -0
  37. data/lib/readers/member_household_list_reader.rb +27 -0
  38. data/lib/readers/person_list_reader.rb +37 -0
  39. data/lib/readers/person_reader.rb +20 -0
  40. data/lib/writers/api_writer.rb +64 -0
  41. data/lib/writers/communication_writer.rb +27 -0
  42. data/lib/writers/contribution_writer.rb +28 -0
  43. data/lib/writers/household_writer.rb +30 -0
  44. data/lib/writers/person_writer.rb +64 -0
  45. data/spec/api/person_spec.rb +21 -0
  46. data/spec/functional/fellowship_one_spec.rb +17 -0
  47. data/spec/readers/api_reader_spec.rb +7 -0
  48. data/spec/spec_helper.rb +47 -0
  49. data/spec/vcr_setup.rb +5 -0
  50. data/spec/writers/api_writer_spec.rb +7 -0
  51. metadata +129 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ef90aa299f36b4c0a571d002270b2ab0b3581b3
4
+ data.tar.gz: adcedccde6a8ecec28f5ba2d645be7ae5f8226fc
5
+ SHA512:
6
+ metadata.gz: 6d6ecceef36ccef3d72218b6ab39413eceedf8b094632f5c3f9852cd59215b8e61b69d4ae15bea024e01a21e480ba7ed960af3dd3170d80a602d2fddb45e9185
7
+ data.tar.gz: 9a7eecf24d55cf41ca22f1a1ff476cc4e0c1787ecd6e8485a5ee8332cb0f83daba2a3c371dba74150a43cfbb073ec8e8acf1cb27f9c0675893ede4603608865b
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ fellowshipone-api-*.gem
2
+ access_token.yml
3
+ access_token_marshal.txt
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ fellowshipone-api
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'typhoeus', '0.6.6'
4
+ gem 'json'
5
+ gem 'oauth_weshays', '0.4.8.pre2'
6
+
7
+ group :development, :test do
8
+ gem 'rspec'
9
+ gem 'debugger'
10
+ gem 'factory_girl'
11
+
12
+ gem 'vcr'
13
+ gem 'webmock', '1.9' # Currently does not work with Typhoeus 0.4.2 - THIS SUCKS!
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,64 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.0.1)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ addressable (2.3.5)
11
+ atomic (1.1.14)
12
+ columnize (0.3.6)
13
+ crack (0.4.1)
14
+ safe_yaml (~> 0.9.0)
15
+ debugger (1.6.2)
16
+ columnize (>= 0.3.1)
17
+ debugger-linecache (~> 1.2.0)
18
+ debugger-ruby_core_source (~> 1.2.3)
19
+ debugger-linecache (1.2.0)
20
+ debugger-ruby_core_source (1.2.3)
21
+ diff-lcs (1.2.5)
22
+ ethon (0.6.1)
23
+ ffi (>= 1.3.0)
24
+ mime-types (~> 1.18)
25
+ factory_girl (4.3.0)
26
+ activesupport (>= 3.0.0)
27
+ ffi (1.9.3)
28
+ i18n (0.6.5)
29
+ json (1.8.1)
30
+ mime-types (1.25)
31
+ minitest (4.7.5)
32
+ multi_json (1.8.2)
33
+ oauth_weshays (0.4.8.pre2)
34
+ rspec (2.14.1)
35
+ rspec-core (~> 2.14.0)
36
+ rspec-expectations (~> 2.14.0)
37
+ rspec-mocks (~> 2.14.0)
38
+ rspec-core (2.14.7)
39
+ rspec-expectations (2.14.4)
40
+ diff-lcs (>= 1.1.3, < 2.0)
41
+ rspec-mocks (2.14.4)
42
+ safe_yaml (0.9.7)
43
+ thread_safe (0.1.3)
44
+ atomic
45
+ typhoeus (0.6.6)
46
+ ethon (~> 0.6.1)
47
+ tzinfo (0.3.38)
48
+ vcr (2.7.0)
49
+ webmock (1.9.0)
50
+ addressable (>= 2.2.7)
51
+ crack (>= 0.1.7)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ debugger
58
+ factory_girl
59
+ json
60
+ oauth_weshays (= 0.4.8.pre2)
61
+ rspec
62
+ typhoeus (= 0.6.6)
63
+ vcr
64
+ webmock (= 1.9)
data/README.rdoc ADDED
@@ -0,0 +1,44 @@
1
+ = FellowshipOne API
2
+
3
+ This Ruby project is an API wrapper for the FellowshipOne API (https://developer.fellowshipone.com/)
4
+
5
+
6
+ == Install / Setup
7
+
8
+ Installing the gem
9
+
10
+ gem install fellowshipone-api
11
+
12
+
13
+ To add it to your Gemfile
14
+
15
+ gem 'fellowshipone-api', :require => 'fellowshipone'
16
+
17
+
18
+ == Example usage
19
+
20
+ Checkout the examples folder.
21
+
22
+
23
+ == Additional resources
24
+
25
+ * FellowshipOne API: https://developer.fellowshipone.com/docs/
26
+ * FellowshipOne Forum: https://developer.fellowshipone.com/forum/
27
+
28
+
29
+ == License
30
+
31
+ This project is released under the MIT license (see LICENSE).
32
+
33
+ This project is maintained by Wes Hays (https://github.com/weshays).
34
+
35
+
36
+ == Contributors
37
+
38
+ Chad Feller: https://github.com/cfeller
39
+ Taylor Brooks: https://github.com/taylorbrooks
40
+
41
+
42
+ == Want to Contribute?
43
+
44
+ If you would like to get involved in this project, then please fork the project. Make changes, add features, write some tests, and then send a pull request.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+ task :test => :spec
7
+
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
11
+ # Put spec opts in a file named .rspec in root
12
+ end
13
+
14
+
15
+ desc "Generate code coverage"
16
+ RSpec::Core::RakeTask.new(:coverage) do |t|
17
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
18
+ t.rcov = true
19
+ t.rcov_opts = ['--exclude', 'spec']
20
+ end
21
+
22
+
23
+
24
+ namespace :docs do
25
+
26
+ desc 'Build the docs for the FellowshipOne API.'
27
+ task :build do
28
+ system('rm -rf doc')
29
+ system('yardoc --no-private --protected lib/**/*.rb')
30
+ end
31
+
32
+ end
@@ -0,0 +1,25 @@
1
+ Gem::Specification.new do |s|
2
+ PROJECT_GEM = 'fellowshipone-api'
3
+ PROJECT_GEM_VERSION = '0.6.0'
4
+
5
+ s.name = PROJECT_GEM
6
+ s.version = PROJECT_GEM_VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+
9
+ s.homepage = 'https://github.com/weshays/fellowshipone-api-ruby'
10
+ s.rubyforge_project = 'Project on www.github.com'
11
+ s.authors = ['Wes Hays', 'Chad Feller']
12
+ s.email = ['weshays@gbdev.com','feller@cs.unr.edu']
13
+
14
+ s.summary = 'Ruby gem/plugin to interact with the FellowshipOne API (https://developer.fellowshipone.com/).'
15
+ s.description = 'Ruby gem/plugin to interact with the FellowshipOne API (https://developer.fellowshipone.com/). Checkout the project on github for more detail.'
16
+
17
+ s.add_dependency('typhoeus', '0.6.6')
18
+ s.add_dependency('oauth_weshays', '0.4.8.pre2')
19
+
20
+
21
+ s.files = `git ls-files`.split("\n").delete_if { |f| !(f =~ /^examples/).nil? }
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,141 @@
1
+ module FellowshipOne
2
+
3
+ # This class is the base class for all FellowshipOne objects and is meant to be inherited.
4
+ #
5
+ class ApiObject
6
+ attr_reader :error_messages, :marked_for_destruction
7
+
8
+
9
+ # Used to specify a list of getters and setters.
10
+ def self.f1_attr_accessor(*vars)
11
+ @__f1_attributes ||= []
12
+ @__f1_attributes.concat(vars)
13
+ attr_accessor(*vars)
14
+ end
15
+
16
+
17
+ # A list of f1_attr_accessors that have been specified.
18
+ def self.__f1_attributes
19
+ @__f1_attributes
20
+ end
21
+
22
+ # Initializes the current object from the JSON data that was loaded into the Hash.
23
+ #
24
+ # @param object_attributes A Hash of values to load into the current object.
25
+ def initialize_from_json_object(object_attributes)
26
+ if object_attributes.is_a?( Hash )
27
+ object_attributes.each do |key, value|
28
+
29
+ method_to_call = "#{_attr_underscore(key.to_s)}="
30
+ if method_to_call.chars.first == "@"
31
+ method_to_call.reverse!.chop!.reverse!
32
+ end
33
+
34
+ if respond_to?(method_to_call)
35
+ self.send(method_to_call, value)
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+
43
+ # # Returns the status of the current object.
44
+ # def is_deleted?
45
+ # @_deleted ||= false
46
+ # end
47
+
48
+ # Gets the current object's attributes in a Hash.
49
+ #
50
+ # @return A hash of all the attributes.
51
+ def to_attributes
52
+ vals = {}
53
+ #vals = {:marked_for_destruction => self.is_deleted?} if self.is_deleted?
54
+ self.class.__f1_attributes.each do |tca|
55
+ rep = self.send(tca)
56
+ if rep.class == Array
57
+ rep.collect! { |r| r.respond_to?(:to_attributes) ? r.to_attributes : r }
58
+ end
59
+ vals[_f1ize(tca)] = rep
60
+ end
61
+ _map_fields(vals)
62
+ vals
63
+ end
64
+
65
+
66
+ # Sets the current object's attributes from a hash
67
+ def set_attributes(attribute_data)
68
+ attribute_data.each { |key, value| self.send("#{key}=", value) if self.respond_to?("#{key}=") }
69
+ end
70
+
71
+
72
+ # Save this object.
73
+ #
74
+ # @return True on success, otherwise false.
75
+ def save
76
+ raise "@writer_object not set for #{self.class}" if @writer_object.nil?
77
+ writer = @writer_object.new(self.to_attributes)
78
+ result = writer.save_object
79
+ if result === false
80
+ @error_messages = writer.error_messages
81
+ else
82
+ rkey = self._default_result_key
83
+ self.initialize_from_json_object(rkey.nil? ? result : result[rkey])
84
+ end
85
+ result === false ? false : true
86
+ end
87
+
88
+
89
+ # # Delete this object.
90
+ # #
91
+ # # @return True on success, otherwise false.
92
+ # def delete
93
+ # writer = @writer_object.new(self.to_attributes)
94
+ # result = writer.delete_object
95
+ # if result === false
96
+ # @error_messages = writer.error_messages
97
+ # else
98
+ # @_deleted = true
99
+ # end
100
+ # result === false ? false : true
101
+ # end
102
+
103
+
104
+ # This method should be overwritten in the ApiObject subclass.
105
+ def _field_map
106
+ {}
107
+ end
108
+
109
+ def _default_result_key
110
+ self.class.to_s.split('::').last.downcase
111
+ end
112
+
113
+ private
114
+
115
+ # Used for mapping FellowshipOne fields that may not match the naming or camelcase
116
+ # used, or that is generated.
117
+ def _map_fields(fields)
118
+ self._field_map.each do |key1, key2|
119
+ fields[key2.to_s] = fields[key1.to_s]
120
+ fields.delete(key1.to_s)
121
+ end
122
+ end
123
+
124
+
125
+ def _attr_underscore(str)
126
+ str.gsub(/::/, '/')
127
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
128
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
129
+ .tr("-", "_")
130
+ .downcase
131
+ end
132
+
133
+ def _f1ize(term)
134
+ term.to_s.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+
@@ -0,0 +1,59 @@
1
+ module FellowshipOne
2
+
3
+ class Communication < ApiObject
4
+
5
+ f1_attr_accessor :id,
6
+ :uri,
7
+ :household,
8
+ :person,
9
+ :communication_type,
10
+ :communication_general_type,
11
+ :communication_value,
12
+ :search_communication_value,
13
+ :preferred,
14
+ :communication_comment,
15
+ :created_date,
16
+ :last_updated_date
17
+
18
+ # Load the communication by the specified ID.
19
+ #
20
+ # @param communication_id The ID of the communication to load.
21
+ #
22
+ # Returns a new Communication object.
23
+ def self.load_by_id(communication_id)
24
+ reader = CommunicationReader.new(nil, communication_id)
25
+ self.new(reader)
26
+ end
27
+
28
+ # Constructor.
29
+ #
30
+ # @param person_id The ID of the person to load the communication for.
31
+ # @param reader (optional) The object that has the data. This can be a CommunicationReader or Hash object.
32
+ def initialize(person_id, reader = nil)
33
+ @writer_object = CommunicationWriter
34
+ if reader.is_a?(CommunicationReader)
35
+ initialize_from_json_object(reader.load_feed['communication'])
36
+ elsif reader.is_a?(Hash)
37
+ initialize_from_json_object(reader)
38
+ else # new
39
+ reader = CommunicationReader.new(person_id, nil)
40
+ initialize_from_json_object(reader.load_new['communication'])
41
+ end
42
+ end
43
+
44
+ def household_id
45
+ self.household['@id']
46
+ end
47
+
48
+ def individual_id
49
+ self.person['@id']
50
+ end
51
+ alias_method :person_id, :individual_id
52
+
53
+ def _field_map
54
+ {:id => '@id',
55
+ :uri => '@uri'}
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,97 @@
1
+ module FellowshipOne
2
+
3
+ class Contribution < ApiObject
4
+
5
+ f1_attr_accessor :id,
6
+ :uri,
7
+ :old_id,
8
+ :account_reference,
9
+ :amount,
10
+ :fund,
11
+ :sub_fund,
12
+ :pledge_drive,
13
+ :household,
14
+ :person,
15
+ :account,
16
+ :reference_image,
17
+ :batch,
18
+ :activity_instance,
19
+ :contribution_type,
20
+ :contribution_sub_type,
21
+ :received_date,
22
+ :transmit_date,
23
+ :return_date,
24
+ :retransmit_date,
25
+ :gl_post_date,
26
+ :is_split,
27
+ :address_verification,
28
+ :memo,
29
+ :stated_value,
30
+ :true_value,
31
+ :thank,
32
+ :thanked_date,
33
+ :is_matched,
34
+ :created_date,
35
+ :created_by_person,
36
+ :last_updated_date,
37
+ :last_updated_by_person
38
+
39
+ # Load the contribution by the specified ID.
40
+ #
41
+ # @param contribution_id The ID of the contribution to load.
42
+ #
43
+ # Returns a new Contribution object.
44
+ def self.load_by_id(contribution_id)
45
+ reader = ContributionReader.new(contribution_id)
46
+ self.new(reader)
47
+ end
48
+
49
+ # Constructor.
50
+ #
51
+ # @param reader (optional) The object that has the data. This can be a ContributionReader or Hash object.
52
+ def initialize(reader = nil)
53
+ @writer_object = ContributionWriter
54
+ if reader.is_a?(ContributionReader)
55
+ initialize_from_json_object(reader.load_feed['contributionReceipt'])
56
+ elsif reader.is_a?(Hash)
57
+ initialize_from_json_object(reader)
58
+ else # new
59
+ reader = ContributionReader.new
60
+ initialize_from_json_object(reader.load_new['contributionReceipt'])
61
+ end
62
+ end
63
+
64
+
65
+ def fund_id
66
+ self.fund['@id']
67
+ end
68
+
69
+ def household_id
70
+ self.household['@id']
71
+ end
72
+
73
+ def individual_id
74
+ self.person['@id']
75
+ end
76
+ alias_method :person_id, :individual_id
77
+
78
+ def amount_cents
79
+ (self.amount.to_f * 100).to_i
80
+ end
81
+
82
+ def instrument_type
83
+ self.contribution_type['name']
84
+ end
85
+
86
+ def _default_result_key
87
+ 'contributionReceipt'
88
+ end
89
+
90
+ def _field_map
91
+ {:id => '@id',
92
+ :uri => '@uri',
93
+ :oldId => '@oldID'}
94
+ end
95
+ end
96
+
97
+ end