church-community-builder 0.1.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.
Files changed (52) hide show
  1. data/.gitignore +3 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +13 -0
  4. data/Gemfile.lock +52 -0
  5. data/README.rdoc +54 -0
  6. data/Rakefile +32 -0
  7. data/ccb_api.gemspec +26 -0
  8. data/docs/batch_implement.pdf +0 -0
  9. data/docs/event_implement.pdf +0 -0
  10. data/docs/group_implement.pdf +0 -0
  11. data/docs/individual_profile_implement.pdf +0 -0
  12. data/docs/pwt_implement.pdf +0 -0
  13. data/docs/pwt_overview.pdf +0 -0
  14. data/examples/batch.rb +50 -0
  15. data/examples/calendar.rb +18 -0
  16. data/examples/campus.rb +13 -0
  17. data/examples/individual.rb +38 -0
  18. data/examples/sync_data.rb +48 -0
  19. data/lib/api/address.rb +28 -0
  20. data/lib/api/api_object.rb +116 -0
  21. data/lib/api/batch.rb +48 -0
  22. data/lib/api/batch_list.rb +50 -0
  23. data/lib/api/campus.rb +29 -0
  24. data/lib/api/campus_list.rb +65 -0
  25. data/lib/api/individual.rb +138 -0
  26. data/lib/api/individual_list.rb +65 -0
  27. data/lib/api/mergeable_individual_list.rb +92 -0
  28. data/lib/api/mergeable_transaction_list.rb +74 -0
  29. data/lib/api/search.rb +81 -0
  30. data/lib/api/transaction.rb +114 -0
  31. data/lib/api/transaction_list.rb +52 -0
  32. data/lib/api/valid_individual.rb +43 -0
  33. data/lib/api/valid_individual_list.rb +49 -0
  34. data/lib/auto_load.rb +17 -0
  35. data/lib/ccb_api.rb +33 -0
  36. data/lib/common.rb +41 -0
  37. data/lib/exceptions.rb +5 -0
  38. data/lib/readers/api_reader.rb +35 -0
  39. data/lib/readers/batch_list_reader.rb +17 -0
  40. data/lib/readers/batch_reader.rb +14 -0
  41. data/lib/readers/campus_list_reader.rb +17 -0
  42. data/lib/readers/individual_list_reader.rb +18 -0
  43. data/lib/readers/individual_reader.rb +14 -0
  44. data/lib/writers/api_writer.rb +64 -0
  45. data/lib/writers/user_writer.rb +46 -0
  46. data/spec/api/user_spec.rb +37 -0
  47. data/spec/factories/user.rb +51 -0
  48. data/spec/functional/ccb_spec.rb +20 -0
  49. data/spec/readers/user_reader_spec.rb +7 -0
  50. data/spec/spec_helper.rb +31 -0
  51. data/spec/writers/user_writer_spec.rb +80 -0
  52. metadata +137 -0
data/lib/common.rb ADDED
@@ -0,0 +1,41 @@
1
+ module ChurchCommunityBuilder
2
+ require 'cgi'
3
+ require 'json'
4
+
5
+ def self.admin_request(method, params = {}, body = nil)
6
+ url = "https://#{ChurchCommunityBuilder::Api.api_subdomain}.ccbchurch.com/api.php"
7
+ username = ChurchCommunityBuilder::Api.api_username
8
+ password = ChurchCommunityBuilder::Api.api_password
9
+
10
+ response =
11
+ case method
12
+ when :post
13
+ Typhoeus::Request.post(url, {:headers => headers, :body => body})
14
+ when :get
15
+ Typhoeus::Request.get(url, params: params, userpwd: username+":"+password)
16
+ when :put
17
+ Typhoeus::Request.put(url, {:headers => headers, :body => body})
18
+ when :delete
19
+ Typhoeus::Request.delete(url, {:headers => headers, :params => params})
20
+ end
21
+
22
+
23
+ unless response.success?
24
+ if response.code > 0
25
+ raise ChurchCommunityBuilderExceptions::UnableToConnectToChurchCommunityBuilder.new(response.body)
26
+ else
27
+ begin
28
+ error_messages = JSON.parse(response.body)['error_message']
29
+ rescue
30
+ response_code_desc = response.headers.partition("\r\n")[0].sub(/^\S+/, '') rescue nil
31
+ raise ChurchCommunityBuilderExceptions::UnknownErrorConnectingToChurchCommunityBuilder.new("Unknown error when connecting to The City.#{response_code_desc}")
32
+ else
33
+ raise ChurchCommunityBuilderExceptions::ChurchCommunityBuilderResponseError.new(error_messages)
34
+ end
35
+ end
36
+ end
37
+
38
+ response
39
+ end
40
+
41
+ end
data/lib/exceptions.rb ADDED
@@ -0,0 +1,5 @@
1
+ module ChurchCommunityBuilderExceptions
2
+ class UnableToConnectToChurchCommunityBuilder < StandardError; end
3
+ class UnknownErrorConnectingToChurchCommunityBuilder < StandardError; end
4
+ class ChurchCommunityBuilderResponseError < StandardError; end
5
+ end
@@ -0,0 +1,35 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ # This adapter is the standard for all loading objects.
4
+ class ApiReader
5
+ attr_reader :headers
6
+
7
+ # Constructor
8
+ # def initialize
9
+ # end
10
+
11
+ # Loads the list
12
+ #
13
+ # @return the data loaded in a JSON object.
14
+ def load_feed
15
+
16
+ @url_data_params ||= {}
17
+ response = ChurchCommunityBuilder::admin_request(:get, @url_data_params)
18
+ data = _xml2json(response.body)
19
+ @headers = response.headers
20
+
21
+ return data
22
+ end
23
+
24
+ private
25
+
26
+ def _xml2json(xml)
27
+ # {KeepRoot: true, ForceArray: false, SuppressEmpty: true} were set to
28
+ # maximize compatibility with Hash.from_xml, used previously.
29
+ #
30
+ XmlSimple.xml_in(xml, {KeepRoot: true, ForceArray: false, SuppressEmpty: true})
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,17 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ class BatchListReader < ApiReader
4
+
5
+ # Constructor.
6
+ #
7
+ def initialize(options = {})
8
+ filter = options[:filter]
9
+ @url_data_params = options[:url_data_params]
10
+
11
+ @url_data_params.merge!({:filter => filter}) if filter
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,14 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ class BatchReader < ApiReader
4
+
5
+ # Constructor.
6
+ #
7
+ # @param person_id The ID of the user to load.
8
+ def initialize(batch_id)
9
+ @url_data_params = {srv: "batch_profile_from_id", id: batch_id}
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,17 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ class CampusListReader < ApiReader
4
+
5
+ # Constructor.
6
+ #
7
+ def initialize(options = {})
8
+ filter = options[:filter]
9
+ @url_data_params = options[:url_data_params]
10
+
11
+ @url_data_params.merge!({:filter => filter}) if filter
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,18 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ # This reader works with both Individual List and ValidIndividualList
4
+ #
5
+ class IndividualListReader < ApiReader
6
+
7
+ # Constructor.
8
+ #
9
+ def initialize(options = {})
10
+ filter = options[:filter]
11
+
12
+ @url_data_params = options[:url_data_params]
13
+ @url_data_params.merge!({:filter => filter}) if filter
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,14 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ class IndividualReader < ApiReader
4
+
5
+ # Constructor.
6
+ #
7
+ # @param individual_id The ID of the user to load.
8
+ def initialize(individual_id)
9
+ @url_data_params = {srv: "individual_profile_from_id", individual_id: individual_id}
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,64 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ # This adapter is the standard for all saving objects.
4
+ class ApiWriter
5
+ attr_reader :error_messages, :response_code
6
+
7
+ # # Saves this object.
8
+ # #
9
+ # # @return True or ID on success, otherwise false.
10
+ # def save_object
11
+ # @url_data_params ||= {}
12
+ # success = true
13
+
14
+ # if @url_data_path.nil?
15
+ # @error_messages = ["#{@url_action.to_s.upcase} not implemented for #{self.class.to_s}"]
16
+ # return false
17
+ # end
18
+
19
+ # if @updatable_fields and !@updatable_fields.empty?
20
+ # fields_to_remove = @url_data_params.keys - @updatable_fields
21
+ # fields_to_remove.each { |ftr| @url_data_params.delete(ftr) }
22
+ # end
23
+
24
+ # begin
25
+ # response = ChurchCommunityBuilder::admin_request(@url_action, @url_data_path, nil, @url_data_params.to_json)
26
+ # @response_code = response.code
27
+ # # No content but is a success
28
+ # success = response.code == 204 ? {'success' => true} : JSON.parse(response.body)
29
+ # rescue Exception => e
30
+ # @error_messages = e.message.split(',')
31
+ # success = false
32
+ # end
33
+
34
+ # return success
35
+ # end
36
+
37
+
38
+ # # Deletes this object.
39
+ # #
40
+ # # @return True or ID on success, otherwise false.
41
+ # def delete_object
42
+ # success = true
43
+
44
+ # if @url_data_delete_path.nil?
45
+ # @error_messages = ["DELETE not implemented for #{self.class.to_s}"]
46
+ # return false
47
+ # end
48
+
49
+ # begin
50
+ # # @url_data_path should be the same as :put if this object is already
51
+ # # setup and mapped to an object that exists
52
+ # response = ChurchCommunityBuilder::admin_request(:delete, @url_data_delete_path)
53
+ # success = response.code == 204 ? true : false # No content but is a success
54
+ # rescue Exception => e
55
+ # @error_messages = e.message.split(',')
56
+ # success = false
57
+ # end
58
+
59
+ # return success
60
+ # end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,46 @@
1
+ module ChurchCommunityBuilder
2
+
3
+ class UserWriter < ApiWriter
4
+
5
+ # Constructor.
6
+ #
7
+ # @param data The json object data to save.
8
+ def initialize(data)
9
+ if data[:id]
10
+ @url_action = :put
11
+ @url_data_path = "/users/#{data[:id]}"
12
+ else
13
+ @url_action = :post
14
+ @url_data_path = "/users"
15
+ end
16
+ @url_data_delete_path = "/users/#{data[:id]}"
17
+
18
+ @url_data_params = data
19
+
20
+ @updatable_fields = [:title,
21
+ :first,
22
+ :middle,
23
+ :last,
24
+ :nickname,
25
+ :gender,
26
+ :email,
27
+ :staff,
28
+ :primary_campus_id,
29
+ :member_since,
30
+ :birthdate,
31
+ :primary_phone,
32
+ :primary_phone_type,
33
+ :secondary_phone,
34
+ :secondary_phone_type,
35
+ :external_id_1,
36
+ :external_id_2,
37
+ :external_id_3,
38
+ :marital_status,
39
+ :is_an_organization]
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+
@@ -0,0 +1,37 @@
1
+ # require File.join(Dir.pwd, 'spec', 'spec_helper')
2
+
3
+ # describe 'User' do
4
+
5
+ # before do
6
+ # simulate_connection_to_server
7
+ # end
8
+
9
+ # after do
10
+
11
+ # end
12
+
13
+ # it 'should pass retrieving a user from list' do
14
+ # request_data = FactoryGirl.attributes_for(:user_list, {
15
+ # :total_entries => 1,
16
+ # :total_pages => 1,
17
+ # :users => [FactoryGirl.attributes_for(:user)]
18
+ # }).to_json
19
+ # TheCity.stub(:admin_request).and_return( TheCityResponse.new(200, request_data) )
20
+
21
+ # user_list = TheCity::UserList.new
22
+
23
+ # user = user_list[0]
24
+ # user.full_name.should == "Sammy Shepherd"
25
+ # end
26
+
27
+
28
+ # it 'should pass retrieving a user' do
29
+ # request_data = FactoryGirl.attributes_for(:user).to_json
30
+ # TheCity.stub(:admin_request).and_return( TheCityResponse.new(200, request_data) )
31
+ # user = TheCity::User.load_by_id(123)
32
+ # user.full_name.should == "Sammy Shepherd"
33
+ # end
34
+
35
+ # end
36
+
37
+
@@ -0,0 +1,51 @@
1
+ # module TheCity
2
+ # FactoryGirl.define do
3
+
4
+ # factory :user, :class => TheCity::User do
5
+ # api_url "https://api.onthecity.org/users/946060874"
6
+ # updated_at "05/15/2012 07:24 AM (UTC)"
7
+ # last_logged_in "05/16/2012 04:52 AM (UTC)"
8
+ # secondary_phone ""
9
+ # last_engaged "05/16/2012 04:52 AM (UTC)"
10
+ # title "Pastor"
11
+ # internal_url "http://local.devthecity.org:3000/users/946060874"
12
+ # id 946060874
13
+ # first "Sam"
14
+ # primary_campus_name nil
15
+ # last "Shepherd"
16
+ # head_of_household true
17
+ # nickname "Sammy"
18
+ # active true
19
+ # primary_phone_type "home"
20
+ # primary_phone ""
21
+ # member_since "05/14/2012"
22
+ # birthdate "1974-11-09"
23
+ # email_bouncing false
24
+ # secondary_phone_type "home"
25
+ # primary_campus_id nil
26
+ # marital_status nil
27
+ # contact_updated_at "05/15/2012 12:24 AM (UTC)"
28
+ # type "User"
29
+ # staff true
30
+ # admin_url "http://church.onthecity.org/admin/users/946060874"
31
+ # created_at "05/14/2012 05:51 PM (UTC)"
32
+ # gender "Male"
33
+ # external_id_1 nil
34
+ # external_id_2 nil
35
+ # external_id_3 nil
36
+ # middle ""
37
+ # email "zack@church.org"
38
+ # last_checkin_date "05/14/2012 05:51 PM (UTC)"
39
+ # last_donation_date "05/14/2012 05:51 PM (UTC)"
40
+ # last_attendance_date "05/14/2012 05:51 PM (UTC)"
41
+ # in_community true
42
+ # in_service true
43
+ # in_welcome true
44
+ # in_campus true
45
+ # in_neighborhood true
46
+ # end
47
+
48
+ # end
49
+ # end
50
+
51
+
@@ -0,0 +1,20 @@
1
+ # require File.join(Dir.pwd, 'spec', 'spec_helper')
2
+
3
+ # describe 'AdminApi' do
4
+
5
+ # before do
6
+ # simulate_connection_to_server
7
+ # end
8
+
9
+ # after do
10
+
11
+ # end
12
+
13
+ # it 'should get a list of users without any paramters'
14
+ # it 'should get a list of users with parameters'
15
+ # it 'should get a user count without any paramters'
16
+ # it 'should get a user count with the specified paramters'
17
+
18
+ # end
19
+
20
+
@@ -0,0 +1,7 @@
1
+ # require 'spec_helper'
2
+
3
+ # describe 'UserReader' do
4
+
5
+ # it 'should pass if ....'
6
+
7
+ # end
@@ -0,0 +1,31 @@
1
+ # # Project:: TheCity Admin API
2
+ # # File:: the_city.rb
3
+ # #
4
+ # # Author:: Wes Hays <weshays@gbdev.com>
5
+ # # Link:: https://github.com/weshays/admin-api-ruby
6
+ # # Package:: TheCity::Admin
7
+
8
+
9
+ # require File.expand_path( File.dirname(__FILE__) + '/../lib/the_city_admin.rb')
10
+
11
+ # require 'rubygems'
12
+ # require 'rspec'
13
+ # require 'ruby-debug'
14
+ # require 'date'
15
+
16
+ # require 'factory_girl'
17
+ # Dir.glob(File.dirname(__FILE__) + "/factories/*").each { |f| require f }
18
+
19
+
20
+ # TheCityResponse = Struct.new(:code, :body, :headers)
21
+
22
+ # RSpec.configure do |config|
23
+ # config.tty = true
24
+ # config.mock_with :rspec
25
+ # config.include FactoryGirl::Syntax::Methods
26
+ # end
27
+
28
+
29
+ # def simulate_connection_to_server
30
+ # @the_city = TheCity::AdminApi.new('cf2903151e3213e66fd8080c7d8b65b1d6ccdd31', '5c88b32edda7653c')
31
+ # end
@@ -0,0 +1,80 @@
1
+ # require 'spec_helper'
2
+
3
+ # describe 'UserWriter' do
4
+
5
+ # it 'should show connection error messages if server cannot be reached' do
6
+ # TheCity.stub(:admin_request) { raise TheCityExceptions::UnableToConnectToTheCity.new('Unable to connect to server') }
7
+ # user_data = FactoryGirl.attributes_for(:user, {:id => nil})
8
+ # user = TheCity::User.new(user_data)
9
+ # user.id.should be_nil
10
+ # user.save.should === false
11
+ # user.id.should be_nil
12
+ # user.error_messages.should == ['Unable to connect to server']
13
+ # end
14
+
15
+
16
+ # it 'should save if all data is valid for new user' do
17
+ # request_data = FactoryGirl.attributes_for(:user, {:id => 12345}).to_json
18
+ # TheCity.stub(:admin_request).and_return( TheCityResponse.new(200, request_data) )
19
+ # user_data = FactoryGirl.attributes_for(:user, {:id => nil})
20
+ # user = TheCity::User.new(user_data)
21
+ # user.id.should be_nil
22
+ # user.save.should === true
23
+ # user.id.should == 12345
24
+ # end
25
+
26
+
27
+ # it 'should show error messages if save fails for new user' do
28
+ # TheCity.stub(:admin_request) { raise TheCityExceptions::TheCityResponseError.new('email address already exists') }
29
+ # user_data = FactoryGirl.attributes_for(:user, {:id => nil})
30
+ # user = TheCity::User.new(user_data)
31
+ # user.id.should be_nil
32
+ # user.save.should === false
33
+ # user.id.should be_nil
34
+ # user.error_messages.should == ['email address already exists']
35
+ # end
36
+
37
+
38
+ # it 'should save if all data is valid for existing user' do
39
+ # request_data = FactoryGirl.attributes_for(:user, {:id => 12345}).to_json
40
+ # TheCity.stub(:admin_request).and_return( TheCityResponse.new(200, request_data) )
41
+ # user_data = FactoryGirl.attributes_for(:user, {:id => 12345})
42
+ # user = TheCity::User.new(user_data)
43
+ # user.id.should == 12345
44
+ # user.save.should === true
45
+ # user.id.should == 12345
46
+ # end
47
+
48
+
49
+ # it 'should show error messages if save fails for existing user' do
50
+ # TheCity.stub(:admin_request) { raise TheCityExceptions::TheCityResponseError.new('something bad happened') }
51
+ # user_data = FactoryGirl.attributes_for(:user, {:id => 12345})
52
+ # user = TheCity::User.new(user_data)
53
+ # user.id.should == 12345
54
+ # user.save.should === false
55
+ # user.id.should == 12345
56
+ # user.error_messages.should == ['something bad happened']
57
+ # end
58
+
59
+
60
+ # it 'should delete if data ID exists for the existing user' do
61
+ # TheCity.stub(:admin_request).and_return( TheCityResponse.new(204, '{}') )
62
+ # user_data = FactoryGirl.attributes_for(:user, {:id => 12345})
63
+ # user = TheCity::User.new(user_data)
64
+ # user.is_deleted?.should === false
65
+ # user.delete
66
+ # user.is_deleted?.should === true
67
+ # end
68
+
69
+
70
+ # it 'should show error messages if data fails to be deleted' do
71
+ # TheCity.stub(:admin_request) { raise TheCityExceptions::TheCityResponseError.new('something bad happened') }
72
+ # user_data = FactoryGirl.attributes_for(:user, {:id => 12345})
73
+ # user = TheCity::User.new(user_data)
74
+ # user.is_deleted?.should === false
75
+ # user.delete
76
+ # user.is_deleted?.should === false
77
+ # user.error_messages.should == ['something bad happened']
78
+ # end
79
+
80
+ # end