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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 895602f68388ac5ca0d367ee33568425ea6b9b94
4
- data.tar.gz: 426048ab8c437b47607fe449af53455ee22a6c14
3
+ metadata.gz: 6cc2774ab10bd28336dd0d4586a9e580339da8fa
4
+ data.tar.gz: 993020dd12dc61dcf601e70b111279f7dbf0dd8b
5
5
  SHA512:
6
- metadata.gz: 2c0c4236c700a3014c6ed84ed1122d4784047016dfc69b2f8431cac9b23bea80832f17858562e1adf86c0eaf8c3367e0fa21d365187197acce034c91c171400f
7
- data.tar.gz: bab4f5d64be4d3bf1f75be0de9d98a1a294307b1fae5af38ee70bee1f26d2ba50c64e70508808d523713c61acb3b94e5e5cdff57c3949a745584aea8c18f4465
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.parent].include?(association.defined_on)
41
+ [self, self.ancestors].flatten.include?(association.defined_on)
35
42
  end
36
43
  end
37
44
  end
@@ -34,8 +34,7 @@ module CapsuleCRM
34
34
  #
35
35
  # Returns an Array of CapsuleCRM::Address objects
36
36
  def addresses=(addresses)
37
- addresses = CapsuleCRM::Address.new(addresses) if addresses.is_a?(Hash)
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
- emails = CapsuleCRM::Email.new(emails) if emails.is_a?(Hash)
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
- phones = CapsuleCRM::Phone.new(phones) if phones.is_a?(Hash)
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
- websites = CapsuleCRM::Website.new(websites) if websites.is_a?(Hash)
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
@@ -3,8 +3,8 @@ module CapsuleCRM
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
- def get(path)
7
- CapsuleCRM::Connection.get(path)
6
+ def get(path, options = {})
7
+ CapsuleCRM::Connection.get(path, options)
8
8
  end
9
9
  end
10
10
  end
@@ -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
- if valid?
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 = {})
@@ -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
@@ -1,3 +1,3 @@
1
1
  module CapsuleCrm
2
- VERSION = '1.3.0'
2
+ VERSION = '1.4.0'
3
3
  end
@@ -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]) }
@@ -50,6 +50,8 @@ describe CapsuleCRM::CustomField do
50
50
  end
51
51
 
52
52
  it 'should have a root element of "customField"' do
53
+ p described_class.serializable_options
54
+ p subject
53
55
  expect(subject.keys.first).to eql('customField')
54
56
  end
55
57
  end
@@ -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
- if described_class.attributes.map(&:name).include?(:track_id)
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.3.0
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-14 00:00:00.000000000 Z
11
+ date: 2014-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel