capsule_crm 1.3.0 → 1.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/capsule_crm/associations/has_many.rb +16 -0
- data/lib/capsule_crm/associations/has_many_proxy.rb +6 -6
- data/lib/capsule_crm/associations.rb +8 -1
- data/lib/capsule_crm/contacts.rb +16 -8
- data/lib/capsule_crm/gettable.rb +2 -2
- data/lib/capsule_crm/organization.rb +3 -0
- data/lib/capsule_crm/persistence/persistable.rb +4 -6
- data/lib/capsule_crm/person.rb +2 -0
- data/lib/capsule_crm/serializer.rb +1 -1
- data/lib/capsule_crm/version.rb +1 -1
- data/spec/lib/capsule_crm/contacts_spec.rb +48 -0
- data/spec/lib/capsule_crm/custom_field_spec.rb +2 -0
- data/spec/lib/capsule_crm/person_spec.rb +5 -0
- data/spec/support/shared_examples/persistable.rb +33 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cc2774ab10bd28336dd0d4586a9e580339da8fa
|
4
|
+
data.tar.gz: 993020dd12dc61dcf601e70b111279f7dbf0dd8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8ff0fcca56968b5f6bcf914c2041e758c2f28c3d16107b2a36f61be649ba35c9741c171619f2197d7ca229b746131a68d6e556e8b440b311413c8611c41b646
|
7
|
+
data.tar.gz: 002ed9d4cb89290cf6151e72439c84912f2752e7b6b4a455d4165aa024b01d4d75c0efbf2b08c5ca65bef995ae9e6bdca176a84bfb17fe8c237c8c1e05bc55fb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.4.0
|
4
|
+
|
5
|
+
- Fix bug with contacts, where contact details were being attached to parties as
|
6
|
+
an array of hashes
|
7
|
+
- Added ActiveModel::Callbacks to persistence module so after_save methods may
|
8
|
+
be added
|
9
|
+
- Used after_save method to save all embedded associations (custom fields)
|
10
|
+
|
3
11
|
## 1.3.0
|
4
12
|
|
5
13
|
- Refactored associations to allow classes to reflect on themselves in order to
|
@@ -39,6 +39,22 @@ module CapsuleCRM
|
|
39
39
|
new(association_name, self, options)
|
40
40
|
self.associations[association_name] = association
|
41
41
|
|
42
|
+
if options[:embedded]
|
43
|
+
define_method "save_#{association_name}" do
|
44
|
+
unless self.send(association_name).blank?
|
45
|
+
# TODO why can't I chain this?
|
46
|
+
a = self.send(association_name)
|
47
|
+
a.save
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class_eval do
|
52
|
+
after_save :"save_#{association_name}" if respond_to?(:after_save)
|
53
|
+
private :"save_#{association_name}"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
42
58
|
define_method association_name do
|
43
59
|
instance_variable_get(:"@#{association_name}") ||
|
44
60
|
instance_variable_set(:"@#{association_name}", association.proxy(self))
|
@@ -44,12 +44,6 @@ module CapsuleCRM
|
|
44
44
|
{ root => serializer.serialize_collection(target_klass, target) }
|
45
45
|
end
|
46
46
|
|
47
|
-
private
|
48
|
-
|
49
|
-
def serializer
|
50
|
-
@serializer ||= ::CapsuleCRM::Serializer
|
51
|
-
end
|
52
|
-
|
53
47
|
def save
|
54
48
|
json = to_capsule_json(target_klass.serializable_options.collection_root)
|
55
49
|
path = [
|
@@ -59,6 +53,12 @@ module CapsuleCRM
|
|
59
53
|
::CapsuleCRM::Connection.put(path, json)
|
60
54
|
end
|
61
55
|
|
56
|
+
private
|
57
|
+
|
58
|
+
def serializer
|
59
|
+
@serializer ||= ::CapsuleCRM::Serializer
|
60
|
+
end
|
61
|
+
|
62
62
|
def save!
|
63
63
|
save
|
64
64
|
end
|
@@ -28,10 +28,17 @@ module CapsuleCRM
|
|
28
28
|
select_associations(:belongs_to)
|
29
29
|
end
|
30
30
|
|
31
|
+
# Public: Get all the embedded has many associations defined on the class
|
32
|
+
def embedded_associations
|
33
|
+
has_many_associations.select do |name, association|
|
34
|
+
association.embedded
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
31
38
|
def select_associations(macro)
|
32
39
|
associations.select do |name, association|
|
33
40
|
association.macro == macro &&
|
34
|
-
[self, self.
|
41
|
+
[self, self.ancestors].flatten.include?(association.defined_on)
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
data/lib/capsule_crm/contacts.rb
CHANGED
@@ -34,8 +34,7 @@ module CapsuleCRM
|
|
34
34
|
#
|
35
35
|
# Returns an Array of CapsuleCRM::Address objects
|
36
36
|
def addresses=(addresses)
|
37
|
-
|
38
|
-
@addresses = Array(addresses)
|
37
|
+
set_collection(CapsuleCRM::Address, addresses)
|
39
38
|
end
|
40
39
|
|
41
40
|
# Public: Gets the addresses for this contacts container
|
@@ -62,10 +61,10 @@ module CapsuleCRM
|
|
62
61
|
#
|
63
62
|
# Returns an Array of CapsuleCRM::Email objects
|
64
63
|
def emails=(emails)
|
65
|
-
|
66
|
-
@emails = Array(emails)
|
64
|
+
set_collection(CapsuleCRM::Email, emails)
|
67
65
|
end
|
68
66
|
|
67
|
+
|
69
68
|
# Public: Gets the emails for this contacts container
|
70
69
|
#
|
71
70
|
# Examples
|
@@ -89,8 +88,7 @@ module CapsuleCRM
|
|
89
88
|
#
|
90
89
|
# Returns an Array of CapsuleCRM::Phone objects
|
91
90
|
def phones=(phones)
|
92
|
-
|
93
|
-
@phones = Array(phones)
|
91
|
+
set_collection(CapsuleCRM::Phone, phones)
|
94
92
|
end
|
95
93
|
|
96
94
|
# Public: Gets the phones for this contacts container
|
@@ -118,8 +116,7 @@ module CapsuleCRM
|
|
118
116
|
#
|
119
117
|
# Returns an Array of CapsuleCRM::Website objects
|
120
118
|
def websites=(websites)
|
121
|
-
|
122
|
-
@websites = Array(websites)
|
119
|
+
set_collection(CapsuleCRM::Website, websites)
|
123
120
|
end
|
124
121
|
|
125
122
|
# Public: Gets the websites for this contacts container
|
@@ -148,5 +145,16 @@ module CapsuleCRM
|
|
148
145
|
website: websites.map(&:to_capsule_json)
|
149
146
|
}.delete_if { |key, value| value.blank? }.stringify_keys
|
150
147
|
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def set_collection(klass, collection)
|
152
|
+
objects = [collection].compact.flatten.map do |item|
|
153
|
+
item.is_a?(Hash) ? klass.new(item) : item
|
154
|
+
end
|
155
|
+
instance_variable_set(
|
156
|
+
:"@#{klass.to_s.downcase.demodulize.pluralize}", objects
|
157
|
+
)
|
158
|
+
end
|
151
159
|
end
|
152
160
|
end
|
data/lib/capsule_crm/gettable.rb
CHANGED
@@ -24,6 +24,7 @@ module CapsuleCRM
|
|
24
24
|
|
25
25
|
persistable_config do |config|
|
26
26
|
config.create = lambda { |org| "organisation" }
|
27
|
+
config.update = lambda { |org| "organisation" }
|
27
28
|
config.destroy = lambda { |org| "party/#{org.id}" }
|
28
29
|
end
|
29
30
|
|
@@ -33,6 +34,8 @@ module CapsuleCRM
|
|
33
34
|
|
34
35
|
validates :name, presence: true
|
35
36
|
|
37
|
+
after_save :save_custom_fields
|
38
|
+
|
36
39
|
has_many :people
|
37
40
|
|
38
41
|
# Public: Get all people from Capsule. The list can be restricted
|
@@ -6,6 +6,8 @@ module CapsuleCRM
|
|
6
6
|
def self.included(base)
|
7
7
|
base.send :include, CapsuleCRM::Persistence::Configuration
|
8
8
|
base.extend CapsuleCRM::Persistence::Persistable::ClassMethods
|
9
|
+
base.extend ActiveModel::Callbacks
|
10
|
+
base.send :define_model_callbacks, :save
|
9
11
|
end
|
10
12
|
|
11
13
|
module ClassMethods
|
@@ -20,18 +22,14 @@ module CapsuleCRM
|
|
20
22
|
|
21
23
|
def save
|
22
24
|
if valid?
|
23
|
-
new_record? ? create_record : update_record
|
25
|
+
run_callbacks(:save) { new_record? ? create_record : update_record }
|
24
26
|
else
|
25
27
|
false
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
31
|
def save!
|
30
|
-
|
31
|
-
new_record? ? create_record : update_record
|
32
|
-
else
|
33
|
-
raise CapsuleCRM::Errors::RecordInvalid.new(self)
|
34
|
-
end
|
32
|
+
save || raise(CapsuleCRM::Errors::RecordInvalid.new(self))
|
35
33
|
end
|
36
34
|
|
37
35
|
def update_attributes(attributes = {})
|
data/lib/capsule_crm/person.rb
CHANGED
@@ -34,6 +34,8 @@ module CapsuleCRM
|
|
34
34
|
|
35
35
|
belongs_to :organization, foreign_key: :organisation_id
|
36
36
|
|
37
|
+
after_save :save_custom_fields
|
38
|
+
|
37
39
|
validates :id, numericality: { allow_blank: true }
|
38
40
|
validates :first_name, presence: { if: :first_name_required? }
|
39
41
|
validates :last_name, presence: { if: :last_name_required? }
|
@@ -18,7 +18,7 @@ module CapsuleCRM
|
|
18
18
|
|
19
19
|
def self.serialize_collection(klass, collection)
|
20
20
|
collection = collection.map do |item|
|
21
|
-
options = klass.serializable_options
|
21
|
+
options = klass.serializable_options.dup
|
22
22
|
options.include_root = false
|
23
23
|
::CapsuleCRM::Serializer.new(options).serialize(item)
|
24
24
|
end
|
data/lib/capsule_crm/version.rb
CHANGED
@@ -25,6 +25,54 @@ describe CapsuleCRM::Contacts do
|
|
25
25
|
)
|
26
26
|
end
|
27
27
|
|
28
|
+
describe '#emails=' do
|
29
|
+
let(:contacts) { CapsuleCRM::Contacts.new }
|
30
|
+
before { contacts.emails = email_attributes }
|
31
|
+
subject { contacts.emails }
|
32
|
+
|
33
|
+
context 'when a hash is supplied' do
|
34
|
+
let(:email_attributes) do
|
35
|
+
{ email_address: 'matt@gmail.com', type: 'Work' }
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should create an email from the attributes' do
|
39
|
+
expect(subject.first).to be_a(CapsuleCRM::Email)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should be an array' do
|
43
|
+
expect(subject).to be_a(Array)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when an array is supplied' do
|
48
|
+
context 'when the array contains hashes' do
|
49
|
+
let(:email_attributes) do
|
50
|
+
[{ email_address: Faker::Internet.email, type: 'Work' }]
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should create an email from the attributes' do
|
54
|
+
expect(subject.first).to be_a(CapsuleCRM::Email)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should be an array' do
|
58
|
+
expect(subject).to be_a(Array)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when the array contains emails' do
|
63
|
+
let(:email) do
|
64
|
+
CapsuleCRM::Email.
|
65
|
+
new(email_address: Faker::Internet.email, type: 'Work')
|
66
|
+
end
|
67
|
+
let(:email_attributes) { [email] }
|
68
|
+
|
69
|
+
it 'should set the emails from the supplied array' do
|
70
|
+
expect(subject).to eql(email_attributes)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
28
76
|
describe '#initialize' do
|
29
77
|
context 'when addresses supplied' do
|
30
78
|
subject { CapsuleCRM::Contacts.new(addresses: [address]) }
|
@@ -36,6 +36,11 @@ describe CapsuleCRM::Person do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
it 'should have embedded custom fields association' do
|
40
|
+
expect(described_class.embedded_associations.keys).
|
41
|
+
to include(:custom_fields)
|
42
|
+
end
|
43
|
+
|
39
44
|
before do
|
40
45
|
stub_request(:get, /\/api\/users$/).
|
41
46
|
to_return(body: File.read('spec/support/all_users.json'))
|
@@ -1,4 +1,13 @@
|
|
1
1
|
shared_examples 'persistable' do |location, id|
|
2
|
+
before do
|
3
|
+
stub_request(:get, /[0-9]*\/customfields/).
|
4
|
+
to_return(body: File.read('spec/support/no_customfields.json'))
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'should add an after_save class method' do
|
8
|
+
expect(described_class).to respond_to(:after_save)
|
9
|
+
end
|
10
|
+
|
2
11
|
describe '.create' do
|
3
12
|
subject { described_class.create attributes }
|
4
13
|
before do
|
@@ -17,7 +26,30 @@ shared_examples 'persistable' do |location, id|
|
|
17
26
|
expect(subject.id).to eql(id)
|
18
27
|
end
|
19
28
|
|
20
|
-
|
29
|
+
described_class.embedded_associations.each do |name, association|
|
30
|
+
context "when the #{described_class} has embedded #{name}" do
|
31
|
+
let(:collection_root) do
|
32
|
+
association.target_klass.serializable_options.collection_root
|
33
|
+
end
|
34
|
+
let(:plural) { association.target_klass.queryable_options.plural }
|
35
|
+
let(:singular) { described_class.queryable_options.singular }
|
36
|
+
before do
|
37
|
+
stub_request(:get, /[0-9]*\/#{plural}/).
|
38
|
+
to_return(body: File.read("spec/support/all_#{plural}.json"))
|
39
|
+
stub_request(:put, /[0-9]*\/#{plural}/).
|
40
|
+
to_return(body: File.read("spec/support/all_#{plural}.json"))
|
41
|
+
end
|
42
|
+
subject { described_class.create attributes }
|
43
|
+
|
44
|
+
it "should save the embedded #{name}" do
|
45
|
+
expect(WebMock).to have_requested(
|
46
|
+
:put, "https://1234:@company.capsulecrm.com/api/#{singular}/#{subject.id}/#{plural}"
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if described_class.attribute_set.map(&:name).include?(:track_id)
|
21
53
|
context "when the #{described_class} has a track" do
|
22
54
|
let(:track) { CapsuleCRM::Track.new(id: Random.rand(1..10)) }
|
23
55
|
subject do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capsule_crm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Beedle
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|