Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# chartmogul-ruby Change Log

## Version 4.12.0 - Mar 16, 2026
- Add `external_id` key to Contact model

## Version 4.11.0 - Jan 6, 2026
- Add new API usage for Customer Subscriptions connect and disconnect
- Update retrieve to accept query params
Expand Down
5 changes: 4 additions & 1 deletion lib/chartmogul/contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Contact < APIResource
writeable_attr :linked_in
writeable_attr :twitter
writeable_attr :notes
writeable_attr :external_id
writeable_attr :custom

include API::Actions::Create
Expand All @@ -43,13 +44,15 @@ def serialize_for_write
if attribute_name == :custom && attribute_value.is_a?(Hash)
payload = attribute_value.each_with_object([]) do |custom_value, arr|
key, value = custom_value
arr << { key: key, value: value }
arr << ({ key:, value: })
end
attributes[:custom] = payload
else
attributes[attribute_name] = attribute_value
end
end
# Include external_id attribute even when nil so callers can explicitly clear it
attributes[:external_id] = nil if instance_variable_defined?(:@external_id) && external_id.nil?
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/chartmogul/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module ChartMogul
VERSION = '4.11.0'
VERSION = '4.12.0'
end
51 changes: 40 additions & 11 deletions spec/chartmogul/contact_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
require 'spec_helper'

describe ChartMogul::Contact do
shared_examples 'creates contact with nil external_id' do
it 'creates the contact correctly' do
contact = described_class.create!(**create_attributes)
expect(contact).to have_attributes(uuid: contact_uuid, external_id: nil)
end
end

let(:attrs) do
{
uuid: contact_uuid,
customer_uuid: customer_uuid,
data_source_uuid: data_source_uuid,
customer_uuid:,
data_source_uuid:,
customer_external_id: 'cus_004',
external_id: 'contact_external_id_001',
first_name: 'First name',
last_name: 'Last name',
position: 9,
Expand All @@ -20,7 +28,7 @@
notes: 'Heading\nBody\nFooter',
custom: {
MyStringAttribute: 'Test',
MyIntegerAttribute: 123,
MyIntegerAttribute: 123
}
}
end
Expand All @@ -29,6 +37,7 @@
let(:data_source_uuid) { 'ds_03cfd2c4-2c7e-11ee-ab23-cb0f008cff46' }
let(:updated_attributes) do
{
external_id: 'contact_external_id_002',
first_name: 'Foo',
last_name: 'Bar',
email: 'contact2@example.com',
Expand Down Expand Up @@ -71,35 +80,55 @@

expect(contact).to have_attributes(
uuid: contact_uuid,
customer_uuid: customer_uuid,
data_source_uuid: data_source_uuid,
customer_uuid:,
data_source_uuid:,
email: 'contact@example.com'
)
end

it 'creates the contact correctly' do
attributes = {
customer_uuid: customer_uuid,
data_source_uuid: data_source_uuid,
email: 'contact@example.com'
customer_uuid:,
data_source_uuid:,
email: 'contact@example.com',
external_id: 'contact_external_id_001'
}
contact = described_class.create!(**attributes)
expect(contact).to have_attributes(uuid: contact_uuid, **attributes)
end

context 'with null external_id' do
let(:create_attributes) do
{ customer_uuid:, data_source_uuid:, email: 'contact@example.com', external_id: nil }
end
include_examples 'creates contact with nil external_id'
end

context 'without external_id' do
let(:create_attributes) do
{ customer_uuid:, data_source_uuid:, email: 'contact@example.com' }
end
include_examples 'creates contact with nil external_id'
end

it 'updates the contact correctly with the class method' do
updated_contact = described_class.update!(
contact_uuid, **updated_attributes
)

expect(updated_contact).to have_attributes(
uuid: contact_uuid,
data_source_uuid: data_source_uuid,
customer_uuid: customer_uuid,
data_source_uuid:,
customer_uuid:,
**updated_attributes
)
end

it 'updates the contact with null external_id correctly' do
updated_contact = described_class.update!(contact_uuid, external_id: nil)
expect(updated_contact).to have_attributes(uuid: contact_uuid, external_id: nil)
end

it 'destroys the contact correctly' do
uuid_to_delete = 'con_ab1e60d4-7690-11ee-84d7-f7e55168a5df'
deleted_contact = described_class.destroy!(uuid: uuid_to_delete)
Expand All @@ -111,7 +140,7 @@
from_uuid = 'con_6f0b7208-7690-11ee-8857-9f75f1321afd'

contact_result = described_class.merge!(
into_uuid: into_uuid, from_uuid: from_uuid
into_uuid:, from_uuid:
)
expect(contact_result).to eq(true)
end
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading