church-community-builder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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