contacts_client 0.0.1

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.
@@ -0,0 +1,15 @@
1
+ class Address < ContactAttribute
2
+ attr_accessor :category, :postal_code, :city, :state, :country
3
+ self.attribute_keys = [:_id, :_type, :public, :primary, :category, :value, :postal_code, :city, :state, :country, :contact_id]
4
+
5
+ self.hydra = Contacts::HYDRA
6
+ self.resource_path = "/v0/contact_attributes"
7
+ self.use_api_key = true
8
+ self.api_key_name = "app_key"
9
+ self.api_key = Contacts::API_KEY
10
+ self.host = Contacts::HOST
11
+
12
+ def _type
13
+ self.class.name
14
+ end
15
+ end
@@ -0,0 +1,40 @@
1
+ class Attachment < LogicalModel
2
+ self.attribute_keys = [:_id, :file, :_type, :public, :name, :description, :contact_id, :account_name]
3
+ self.hydra = Contacts::HYDRA
4
+ self.resource_path = "/v0/attachments"
5
+ self.use_api_key = true
6
+ self.api_key_name = "app_key"
7
+ self.api_key = Contacts::API_KEY
8
+ self.host = Contacts::HOST
9
+
10
+ attr_accessor :name, :description, :file, :public, :primary
11
+
12
+ def new_record?
13
+ self._id.blank?
14
+ end
15
+
16
+ def always_public?
17
+ false
18
+ end
19
+
20
+ def json_root
21
+ :attachment
22
+ end
23
+
24
+ def to_key
25
+ [self._id]
26
+ end
27
+
28
+ def id
29
+ self._id
30
+ end
31
+
32
+ def id= id
33
+ self._id = id
34
+ end
35
+
36
+
37
+ def _type
38
+ self.class.name
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ class Avatar < LogicalModel
2
+ self.hydra = Contacts::HYDRA
3
+
4
+ self.resource_path = "/v0/avatar"
5
+ self.attribute_keys = [:file]
6
+ self.use_api_key = true
7
+ self.api_key_name = "app_key"
8
+ self.api_key = Contacts::API_KEY
9
+ self.host = Contacts::HOST
10
+ end
@@ -0,0 +1,78 @@
1
+ class ContactAttribute < LogicalModel
2
+
3
+ AVAILABLE_TYPES = %w(telephone email identification address date_attribute custom_attribute)
4
+
5
+ attr_accessor :public, :primary
6
+
7
+ self.attribute_keys = [:_id, :_type, :value, :public, :primary, :contact_id, :account_name]
8
+
9
+ self.hydra = Contacts::HYDRA
10
+ self.resource_path = "/v0/contact_attributes"
11
+ self.use_api_key = true
12
+ self.api_key_name = "app_key"
13
+ self.api_key = Contacts::API_KEY
14
+ self.host = Contacts::HOST
15
+
16
+ def new_record?
17
+ self._id.blank?
18
+ end
19
+
20
+ def always_public?
21
+ false
22
+ end
23
+
24
+ validates :value, :presence => true, :unless => proc { self.is_a? DateAttribute }
25
+
26
+ def json_root
27
+ :contact_attribute
28
+ end
29
+
30
+ def to_key
31
+ [self._id]
32
+ end
33
+
34
+ def id
35
+ self._id
36
+ end
37
+
38
+ def id= id
39
+ self._id = id
40
+ end
41
+
42
+ #
43
+ # creates model.
44
+ # Override to set the primary boolean based on what is returned from the service
45
+ # TODO this could be done in an after_create
46
+ def _create(params = {})
47
+ return false unless valid?
48
+
49
+ params = { self.json_root => self.attributes }.merge(params)
50
+ params = self.class.merge_key(params)
51
+
52
+ response = nil
53
+
54
+ Timeout::timeout(self.class.timeout/1000) do
55
+ response = Typhoeus::Request.post( self.class.resource_uri, :params => params, :timeout => self.class.timeout )
56
+ end
57
+ if response.code == 201
58
+ log_ok(response)
59
+ self.id = ActiveSupport::JSON.decode(response.body)["id"]
60
+ #Set as primary according to json returned from service
61
+ self.primary = ActiveSupport::JSON.decode(response.body)["primary"]
62
+ return true
63
+ elsif response.code == 400
64
+ log_failed(response)
65
+ ws_errors = ActiveSupport::JSON.decode(response.body)["errors"]
66
+ ws_errors.each_key do |k|
67
+ self.errors.add k, ws_errors[k]
68
+ end
69
+ return false
70
+ else
71
+ log_failed(response)
72
+ return nil
73
+ end
74
+ rescue Timeout::Error
75
+ self.class.logger.warn "timeout"
76
+ return nil
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+ class ContactsMerge < LogicalModel
3
+
4
+ self.hydra = Contacts::HYDRA
5
+
6
+ self.resource_path = "/v0/merges"
7
+ self.attribute_keys =
8
+ [
9
+ :id,
10
+ :first_contact_id,
11
+ :second_contact_id,
12
+ :state
13
+ ]
14
+ self.use_api_key = true
15
+ self.api_key_name = "app_key"
16
+ self.api_key = Contacts::API_KEY
17
+ self.host = Contacts::HOST
18
+
19
+ def json_root
20
+ 'merge'
21
+ end
22
+
23
+ # Returns a Hash with the message corresponding
24
+ # to last create result
25
+ # @return [Hash]
26
+ # @example { alert: 'error' }
27
+ # @example { notice: 'success' }
28
+ def last_create_message_hash
29
+ case self.last_response_code
30
+ when 400
31
+ if self.errors.keys.include?(:similarity_of_contacts)
32
+ {alert: I18n.t('contacts_merge.not_similar')}
33
+ else
34
+ {alert: self.errors.messages}
35
+ end
36
+ when 401
37
+ {alert: I18n.t('contacts_merge.not_allowed', more: "[<a href='http://www.padma-support.com.ar/blog/n%C4%81o-tenho-permiss%C5%8Des-para-fundir-contatos' target='_blank'>?</a>]").html_safe}
38
+ when 201
39
+ {notice: I18n.t('contacts_merge.merged')}
40
+ when 202
41
+ case self.state
42
+ when 'pending_confirmation'
43
+ {notice: I18n.t('contacts_merge.pending_confirmation_of_admin')}
44
+ else
45
+ {notice: I18n.t('contacts_merge.started')}
46
+ end
47
+ else
48
+ {alert: I18n.t('contacts.communication_failure')}
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,16 @@
1
+ class CustomAttribute < ContactAttribute
2
+ self.attribute_keys = [:_id, :_type, :public, :primary, :name, :value, :contact_id]
3
+ self.hydra = Contacts::HYDRA
4
+ self.resource_path = "/v0/contact_attributes"
5
+ self.use_api_key = true
6
+ self.api_key_name = "app_key"
7
+ self.api_key = Contacts::API_KEY
8
+ self.host = Contacts::HOST
9
+
10
+ attr_accessor :name, :value, :public, :primary
11
+
12
+ def _type
13
+ self.class.name
14
+ end
15
+
16
+ end
@@ -0,0 +1,33 @@
1
+ class DateAttribute < ContactAttribute
2
+ self.attribute_keys = [:_id, :_type, :public, :primary, :category, :contact_id, :year, :month, :day, :value]
3
+ self.hydra = Contacts::HYDRA
4
+ self.resource_path = "/v0/contact_attributes"
5
+ self.use_api_key = true
6
+ self.api_key_name = "app_key"
7
+ self.api_key = Contacts::API_KEY
8
+ self.host = Contacts::HOST
9
+
10
+ attr_accessor :category, :public, :primary
11
+
12
+ validate :valid_date
13
+
14
+ before_save :set_value
15
+
16
+ def _type
17
+ self.class.name
18
+ end
19
+
20
+ private
21
+
22
+ def set_value
23
+ y = year.blank?? 0 : year.to_i
24
+ self.value = Date.civil(y,month.to_i,day.to_i) if Date.valid_civil?(y,month.to_i,day.to_i)
25
+ end
26
+
27
+ def valid_date
28
+ y = year.blank?? 2011 : year # 2011 is a leap year
29
+ unless Date.valid_civil?(y.to_i,month.to_i,day.to_i)
30
+ errors.add(nil)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ class Email < ContactAttribute
2
+ self.attribute_keys = [:_id, :_type, :public, :primary, :category, :value, :contact_id]
3
+ self.hydra = Contacts::HYDRA
4
+ self.resource_path = "/v0/contact_attributes"
5
+ self.use_api_key = true
6
+ self.api_key_name = "app_key"
7
+ self.api_key = Contacts::API_KEY
8
+ self.host = Contacts::HOST
9
+
10
+ attr_accessor :category, :value, :public, :primary
11
+
12
+ def _type
13
+ self.class.name
14
+ end
15
+
16
+ validates :value, :email_format => true
17
+ end
@@ -0,0 +1,20 @@
1
+ class Identification < ContactAttribute
2
+ attr_accessor :category, :value, :public, :primary
3
+
4
+ self.attribute_keys = [:_id, :_type, :public, :primary, :category, :value, :contact_id]
5
+
6
+ self.hydra = Contacts::HYDRA
7
+ self.resource_path = "/v0/contact_attributes"
8
+ self.use_api_key = true
9
+ self.api_key_name = "app_key"
10
+ self.api_key = Contacts::API_KEY
11
+ self.host = Contacts::HOST
12
+
13
+ def _type
14
+ self.class.name
15
+ end
16
+
17
+ def always_public?
18
+ true
19
+ end
20
+ end
@@ -0,0 +1,219 @@
1
+ # encoding: UTF-8
2
+ # wrapper for PADMA-Contacts API interaction
3
+ # Configuration for LogicalModel on /config/initializers/logical_model.rb
4
+ class PadmaContact < LogicalModel
5
+
6
+ self.hydra = Contacts::HYDRA
7
+ self.resource_path = "/v0/contacts"
8
+ self.attribute_keys =
9
+ [
10
+ :_id,
11
+ :first_name, :last_name,
12
+ :gender,
13
+ :avatar,
14
+ :status,
15
+ :local_status, # will only be setted if #find specifies account_name
16
+ :local_statuses,
17
+ :last_local_status,
18
+ :local_teacher,
19
+ :global_teacher_username,
20
+ :level,
21
+ :coefficient, # will only be setted if #find specifies account_name
22
+ :coefficients_counts,
23
+ :owner_name,
24
+ :linked, # will only be setted if #find specifies account_name
25
+ :check_duplicates,
26
+ :email, # Primary email (contact attribute)
27
+ :telephone, # Primary telephone (contact attribute)
28
+ :in_active_merge
29
+ ]
30
+ self.has_many_keys = [:contact_attributes, :attachments]
31
+ self.use_api_key = true
32
+ self.api_key_name = "app_key"
33
+ self.api_key = Contacts::API_KEY
34
+ self.host = Contacts::HOST
35
+
36
+ self.enable_delete_multiple = true
37
+
38
+ validates_presence_of :first_name
39
+ validates_inclusion_of :gender, in: %W(male female), allow_blank: true
40
+
41
+ validates_associated :contact_attributes
42
+ validates_associated :attachments
43
+
44
+ def json_root
45
+ :contact
46
+ end
47
+
48
+ TIMEOUT = 5500 # miliseconds
49
+ PER_PAGE = 9999
50
+
51
+ VALID_LEVELS = %W(aspirante sádhaka yôgin chêla graduado asistente docente maestro)
52
+ validates_inclusion_of :level, in: VALID_LEVELS, allow_blank: true
53
+
54
+ VALID_STATUSES = %W(student former_student prospect)
55
+ validates_inclusion_of :local_status, in: VALID_STATUSES, allow_blank: true
56
+ validates_inclusion_of :status, in: VALID_STATUSES, allow_blank: true
57
+
58
+ VALID_COEFFICIENTS = %W(unknown fp pmenos perfil pmas)
59
+ validates_inclusion_of :coefficient, in: VALID_COEFFICIENTS, allow_blank: true
60
+
61
+ def id
62
+ self._id
63
+ end
64
+
65
+ def id= id
66
+ self._id = id
67
+ end
68
+
69
+ # @return [Array<Communication>]
70
+ def communications
71
+ Communication.where(contact_id: self.id)
72
+ end
73
+
74
+ # @return [Array<Comment>]
75
+ def comments
76
+ Comment.where(contact_id: self.id)
77
+ end
78
+
79
+ # @return [Array<Communication>]
80
+ def subscription_changes
81
+ SubscriptionChange.where(contact_id: self.id)
82
+ end
83
+
84
+ # @argument [Hash] options
85
+ # @return [Array<ActivityStream::Activity>]
86
+ def activities(options={})
87
+ ActivityStream::Activity.paginate(options.merge({where: {target_id: self.id, target_type: 'Contact'}}))
88
+ end
89
+
90
+ def linked?
91
+ self.linked
92
+ end
93
+
94
+ def persisted?
95
+ self._id.present?
96
+ end
97
+
98
+ ContactAttribute::AVAILABLE_TYPES.each do |type|
99
+ define_method(type.to_s.pluralize) { self.contact_attributes.reject {|attr| !attr.is_a? type.to_s.camelize.constantize} }
100
+ end
101
+
102
+ def mobiles
103
+ self.contact_attributes.select{|attr| attr.is_a?(Telephone) && attr.category == "mobile"}
104
+ end
105
+
106
+ def non_mobile_phones
107
+ self.contact_attributes.select{|attr| attr.is_a?(Telephone) && attr.category != "mobile"}
108
+ end
109
+
110
+ def former_student_at
111
+ local_statuses.select{|s|s['value']=='former_student'}.map{|s|s['account_name']}
112
+ end
113
+
114
+ def prospect_at
115
+ local_statuses.select{|s|s['value']=='prospect'}.map{|s|s['account_name']}
116
+ end
117
+
118
+ def check_duplicates
119
+ @check_duplicates || false
120
+ end
121
+
122
+ # @return [Array<PadmaContac>] posible duplicates of this contact
123
+ def possible_duplicates
124
+ possible_duplicates = []
125
+ unless self.errors[:possible_duplicates].empty?
126
+ self.errors[:possible_duplicates][0][0].each do |pd|
127
+ possible_duplicates << PadmaContact.new(pd) #"#{pd["first_name"]} #{pd["last_name"]}"
128
+ end
129
+ end
130
+ possible_duplicates
131
+ end
132
+
133
+ # Returns total amount of coefficients this contact has assigned
134
+ # @return [ Integer ]
135
+ def coefficients_total
136
+ self.coefficients_counts.nil?? 0 : self.coefficients_counts.inject(0){|sum,key_value| sum += key_value[1]}
137
+ end
138
+
139
+ def in_active_merge?
140
+ self.in_active_merge
141
+ end
142
+
143
+ # Links contact to given account
144
+ #
145
+ # @param [String] contact_id
146
+ # @param [String] account_name
147
+ #
148
+ # returns:
149
+ # @return false if linking failed
150
+ # @return nil if there was a connection problem
151
+ # @return true if successfull
152
+ #
153
+ # @example
154
+ # @contact.link_to(account)
155
+ def self.link(contact_id, account_name)
156
+ params = { account_name: account_name }
157
+ params = self.merge_key(params)
158
+
159
+ response = nil
160
+ Timeout::timeout(self.timeout/1000) do
161
+ response = Typhoeus::Request.post( self.resource_uri(contact_id)+"/link", :params => params, :timeout => self.timeout )
162
+ end
163
+ case response.code
164
+ when 200
165
+ log_ok response
166
+ return true
167
+ when 400
168
+ log_failed response
169
+ return false
170
+ else
171
+ log_failed response
172
+ return nil
173
+ end
174
+ rescue Timeout::Error
175
+ self.logger.warn "timeout"
176
+ return nil
177
+ end
178
+
179
+ ##
180
+ # Search is same as paginate but will make POST /search request instead of GET /index
181
+ #
182
+ # Parameters:
183
+ # @param options [Hash].
184
+ # Valid options are:
185
+ # * :page - indicated what page to return. Defaults to 1.
186
+ # * :per_page - indicates how many records to be returned per page. Defauls to 9999
187
+ # * all other options will be sent in :params to WebService
188
+ #
189
+ # Usage:
190
+ # Person.search(:page => params[:page])
191
+ def self.search(options = {})
192
+ options[:page] ||= 1
193
+ options[:per_page] ||= 9999
194
+
195
+ options = self.merge_key(options)
196
+
197
+ response = Typhoeus.post(self.resource_uri+'/search', body: options)
198
+
199
+
200
+ if response.success?
201
+ log_ok(response)
202
+ result_set = self.from_json(response.body)
203
+
204
+ # this paginate is will_paginate's Array pagination
205
+ return Kaminari.paginate_array(
206
+ result_set[:collection],
207
+ {
208
+ :total_count=>result_set[:total],
209
+ :limit => options[:per_page],
210
+ :offset => options[:per_page] * ([options[:page], 1].max - 1)
211
+ }
212
+ )
213
+ else
214
+ log_failed(response)
215
+ return nil
216
+ end
217
+ end
218
+
219
+ end
@@ -0,0 +1,21 @@
1
+ class Telephone < ContactAttribute
2
+ self.attribute_keys = [:_id, :_type, :public, :primary, :category, :value, :contact_id]
3
+ self.hydra = Contacts::HYDRA
4
+ self.resource_path = "/v0/contact_attributes"
5
+ self.use_api_key = true
6
+ self.api_key_name = "app_key"
7
+ self.api_key = Contacts::API_KEY
8
+ self.host = Contacts::HOST
9
+
10
+ attr_accessor :category, :value, :public, :primary
11
+
12
+ validates :value, :numericality => true, :unless => :masked?
13
+
14
+ def masked?
15
+ value.present? && value.last == '#'
16
+ end
17
+
18
+ def _type
19
+ self.class.name
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ if(defined?(Rails))
2
+ module Contacts
3
+
4
+ unless defined? HYDRA
5
+ HYDRA = Typhoeus::Hydra.new
6
+ end
7
+
8
+ HOST = case Rails.env
9
+ when "production"
10
+ "padma-contacts.herokuapp.com"
11
+ when "staging"
12
+ "padma-contacts-staging.herokuapp.com"
13
+ when "development"
14
+ "localhost:3002"
15
+ when "test"
16
+ "localhost:3002"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ # this module assumes base class has a contact_id attribute.
2
+ # expects base class to respond to :account_name
3
+ module BelongsToContact
4
+
5
+ def self.included(base)
6
+ base.send(:validate, :padma_contact_setted_correctly)
7
+ end
8
+
9
+ attr_accessor :padma_contact
10
+ ##
11
+ # Returns associated contact.
12
+ #
13
+ # contact is stored in instance variable padma_contact. This allows for it to be setted in a Mass-Load.
14
+ #
15
+ # @param options [Hash]
16
+ # @option options [TrueClass] decorated - returns decorated contact
17
+ # @option options [TrueClass] force_service_call - forces call to contacts-ws
18
+ # @return [PadmaContact / PadmaContactDecorator]
19
+ def contact(options={})
20
+ if self.padma_contact.nil? || options[:force_service_call]
21
+ self.padma_contact = PadmaContact.find(contact_id, {:account_name => self.account_name})
22
+ end
23
+ ret = padma_contact
24
+ if options[:decorated] && padma_contact
25
+ ret = PadmaContactDecorator.decorate(padma_contact)
26
+ end
27
+ ret
28
+ end
29
+
30
+ private
31
+
32
+ # If padma_contact is setted with a PadmaContact that doesn't match
33
+ # contact_id an exception will be raised
34
+ # @raises 'This is the wrong contact!'
35
+ # @raises 'This is not a contact!'
36
+ def padma_contact_setted_correctly
37
+ return if self.padma_contact.nil?
38
+ unless padma_contact.is_a?(PadmaContact)
39
+ raise 'This is not a contact!'
40
+ end
41
+ if padma_contact.id != self.contact_id
42
+ if self.contact_id.nil?
43
+ # if they differ because contact_id is nil we set it here
44
+ self.contact_id = self.padma_contact.id
45
+ else
46
+ raise 'This is the wrong contact!'
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ module ContactsClient
2
+ class Engine < Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ shared_examples_for "it belongs to a contact" do
2
+ it { should validate_presence_of :contact_id }
3
+ it "should return account on #contact" do
4
+ PadmaContact.should_receive(:find).with(object.contact_id).and_return(PadmaContact.new(contact_id: object.contact_id))
5
+ object.contact.should be_a(PadmaContact)
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'logical_model'
2
+ if defined?(Rails)
3
+ require 'contacts/railties'
4
+ require 'contacts/belongs_to_contact'
5
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: contacts_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dwayne Macgowan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: logical_model
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.4.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.1
46
+ description: This is client library for padma-Contacts-ws
47
+ email:
48
+ - dwaynemac@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - app/models/date_attribute.rb
54
+ - app/models/address.rb
55
+ - app/models/identification.rb
56
+ - app/models/email.rb
57
+ - app/models/telephone.rb
58
+ - app/models/custom_attribute.rb
59
+ - app/models/padma_contact.rb
60
+ - app/models/contacts_merge.rb
61
+ - app/models/attachment.rb
62
+ - app/models/contact_attribute.rb
63
+ - app/models/avatar.rb
64
+ - lib/contacts_client.rb
65
+ - lib/contacts/shared_examples.rb
66
+ - lib/contacts/railties.rb
67
+ - lib/contacts/belongs_to_contact.rb
68
+ - config/initializers/contacts_client.rb
69
+ homepage: ''
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.24
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Client library for padma-contacts-ws
93
+ test_files: []
94
+ has_rdoc: