marketo-api-ruby 0.8
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 +15 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.gemtest +0 -0
- data/Contributing.rdoc +65 -0
- data/Gemfile +9 -0
- data/History.rdoc +3 -0
- data/Licence.rdoc +24 -0
- data/Manifest.txt +32 -0
- data/README.rdoc +105 -0
- data/Rakefile +65 -0
- data/lib/marketo-api-ruby.rb +1 -0
- data/lib/marketo_api.rb +39 -0
- data/lib/marketo_api/campaigns.rb +194 -0
- data/lib/marketo_api/client.rb +169 -0
- data/lib/marketo_api/client_proxy.rb +104 -0
- data/lib/marketo_api/lead.rb +277 -0
- data/lib/marketo_api/leads.rb +150 -0
- data/lib/marketo_api/lists.rb +109 -0
- data/lib/marketo_api/mobject.rb +272 -0
- data/lib/marketo_api/mobjects.rb +115 -0
- data/spec/marketo/authentication_header_spec.rb +66 -0
- data/spec/marketo/client_spec.rb +363 -0
- data/spec/marketo/lead_key_spec.rb +40 -0
- data/spec/marketo/lead_record_spec.rb +86 -0
- data/spec/spec_helper.rb +4 -0
- data/test/marketo_api/test_campaigns.rb +173 -0
- data/test/marketo_api/test_client.rb +83 -0
- data/test/marketo_api/test_lead.rb +158 -0
- data/test/marketo_api/test_leads.rb +133 -0
- data/test/marketo_api/test_lists.rb +95 -0
- data/test/marketo_api/test_mobject.rb +273 -0
- data/test/marketo_api/test_mobjects.rb +158 -0
- data/test/minitest_helper.rb +69 -0
- data/test/test_marketo_api.rb +38 -0
- metadata +302 -0
- metadata.gz.sig +3 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
require_relative 'client_proxy'
|
2
|
+
require_relative 'lead'
|
3
|
+
|
4
|
+
# Implements Lead operations for Marketo.
|
5
|
+
class MarketoAPI::Leads < MarketoAPI::ClientProxy
|
6
|
+
# Implements
|
7
|
+
# {+getLead+}[http://developers.marketo.com/documentation/soap/getlead/],
|
8
|
+
# returning a MarketoAPI::Lead object.
|
9
|
+
#
|
10
|
+
# :call-seq:
|
11
|
+
# get(lead_key)
|
12
|
+
# get(key_type, key_value)
|
13
|
+
def get(type_or_key, value = nil)
|
14
|
+
key = case type_or_key
|
15
|
+
when Hash
|
16
|
+
if lk = type_or_key[:lead_key]
|
17
|
+
if MarketoAPI::Lead.send(:key_type, lk[:key_type])
|
18
|
+
type_or_key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
when MarketoAPI::Lead
|
22
|
+
transform_param(__method__, type_or_key)
|
23
|
+
else
|
24
|
+
MarketoAPI::Lead.key(type_or_key, value)
|
25
|
+
end
|
26
|
+
|
27
|
+
unless key
|
28
|
+
raise ArgumentError, ':type_or_key is not a valid lead key'
|
29
|
+
end
|
30
|
+
extract_from_response(call(:get_lead, key), :lead_record_list) { |record|
|
31
|
+
MarketoAPI::Lead.from_soap_hash(record[:lead_record]) do |lead|
|
32
|
+
lead.proxy = self
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Implements
|
38
|
+
# {+syncLead+}[http://developers.marketo.com/documentation/soap/synclead/],
|
39
|
+
# returning a MarketoAPI::Lead object.
|
40
|
+
def sync(lead_record)
|
41
|
+
extract_from_response(
|
42
|
+
call(:sync_lead, transform_param(__method__, lead_record)),
|
43
|
+
) { |record|
|
44
|
+
MarketoAPI::Lead.from_soap_hash(record[:lead_record]) do |lead|
|
45
|
+
lead.proxy = self
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_multiple(selector) #:nodoc:
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
|
54
|
+
# Implements
|
55
|
+
# {+syncMultipleLeads+}[http://developers.marketo.com/documentation/soap/syncmultipleleads/],
|
56
|
+
# returning an array of MarketoAPI::Lead objects.
|
57
|
+
#
|
58
|
+
# May optionally disable de-duplication by passing <tt>dedup_enabled:
|
59
|
+
# false</tt>.
|
60
|
+
#
|
61
|
+
# :call-seq:
|
62
|
+
# sync_multiple(leads)
|
63
|
+
# sync_multiple(leads, dedup_enabled: false)
|
64
|
+
def sync_multiple(leads, options = { dedup_enabled: true })
|
65
|
+
response = call(
|
66
|
+
:sync_multiple_leads,
|
67
|
+
dedup_enabled: options[:dedup_enabled],
|
68
|
+
lead_record_list: transform_param_list(:sync, leads)
|
69
|
+
)
|
70
|
+
extract_from_response(response, :lead_record_list) do |list|
|
71
|
+
list.each do |record|
|
72
|
+
MarketoAPI::Lead.from_soap_hash(record[:lead_record]) do |lead|
|
73
|
+
lead.proxy = self
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def merge(winning_key, losing_keys) #:nodoc:
|
80
|
+
raise NotImplementedError
|
81
|
+
end
|
82
|
+
|
83
|
+
def activity(lead_key, options = {}) #:nodoc:
|
84
|
+
raise NotImplementedError
|
85
|
+
end
|
86
|
+
|
87
|
+
def changes(start_position, options = {}) #:nodoc:
|
88
|
+
raise NotImplementedError
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# :method: get_by_id
|
93
|
+
# :call-seq: get_by_id(marketo_id)
|
94
|
+
#
|
95
|
+
# Gets the Lead by the provided Marketo ID.
|
96
|
+
|
97
|
+
##
|
98
|
+
# :method: get_by_cookie
|
99
|
+
# :call-seq: get_by_cookie(cookie)
|
100
|
+
#
|
101
|
+
# Gets the Lead by the provided Marketo Munchkin cookie.
|
102
|
+
|
103
|
+
##
|
104
|
+
# :method: get_by_email
|
105
|
+
# :call-seq: get_by_email(email)
|
106
|
+
#
|
107
|
+
# Gets the Lead by the provided lead email.
|
108
|
+
|
109
|
+
##
|
110
|
+
# :method: get_by_lead_owner_email
|
111
|
+
# :call-seq: get_by_lead_owner_email(lead_owner_email)
|
112
|
+
#
|
113
|
+
# Gets the Lead by the provided Lead Owner email.
|
114
|
+
|
115
|
+
##
|
116
|
+
# :method: get_by_salesforce_account_id
|
117
|
+
# :call-seq: get_by_salesforce_account_id(salesforce_account_id)
|
118
|
+
#
|
119
|
+
# Gets the Lead by the provided SFDC Account ID.
|
120
|
+
|
121
|
+
##
|
122
|
+
# :method: get_by_salesforce_contact_id
|
123
|
+
# :call-seq: get_by_salesforce_contact_id(salesforce_contact_id)
|
124
|
+
#
|
125
|
+
# Gets the Lead by the provided SFDC Contact ID.
|
126
|
+
|
127
|
+
##
|
128
|
+
# :method: get_by_salesforce_lead_id
|
129
|
+
# :call-seq: get_by_salesforce_lead_id(salesforce_lead_id)
|
130
|
+
#
|
131
|
+
# Gets the Lead by the provided SFDC Lead ID.
|
132
|
+
|
133
|
+
##
|
134
|
+
# :method: get_by_salesforce_lead_owner_id
|
135
|
+
# :call-seq: get_by_salesforce_lead_owner_id(salesforce_lead_owner_id)
|
136
|
+
#
|
137
|
+
# Gets the Lead by the provided SFDC Lead Owner ID.
|
138
|
+
|
139
|
+
##
|
140
|
+
# :method: get_by_salesforce_opportunity_id
|
141
|
+
# :call-seq: get_by_salesforce_opportunity_id(salesforce_opportunity_id)
|
142
|
+
#
|
143
|
+
# Gets the Lead by the provided SFDC Opportunity ID.
|
144
|
+
|
145
|
+
MarketoAPI::Lead::NAMED_KEYS.each_pair { |name, key|
|
146
|
+
define_method(:"get_by_#{name}") do |value|
|
147
|
+
get(key, value)
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative 'client_proxy'
|
2
|
+
|
3
|
+
# Marketo list operations.
|
4
|
+
class MarketoAPI::Lists < MarketoAPI::ClientProxy
|
5
|
+
NAMED_TYPES = { #:nodoc:
|
6
|
+
name: :MKTOLISTNAME,
|
7
|
+
sales_user_id: :MKTOSALESUSERID,
|
8
|
+
salesforce_lead_owner_id: :SFDCLEADOWNERID
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
TYPES = NAMED_TYPES.values.freeze
|
12
|
+
|
13
|
+
##
|
14
|
+
# :method: add
|
15
|
+
# :call-seq:
|
16
|
+
# add(list_key, options)
|
17
|
+
#
|
18
|
+
# === Options
|
19
|
+
#
|
20
|
+
# +leads+:: Required. An array of Lead objects or lead keys. If both
|
21
|
+
# +leads+ and +lead+ are provided, they will be merged.
|
22
|
+
# +lead+:: An alias for +leads+.
|
23
|
+
# +strict+:: If +true+, the entire operation fails if any subset fails.
|
24
|
+
# Non-strict mode will complete everything it can and return
|
25
|
+
# errors for anything that failed.
|
26
|
+
#
|
27
|
+
# Add leads to a Marketo list.
|
28
|
+
|
29
|
+
##
|
30
|
+
# :method: remove
|
31
|
+
# :call-seq:
|
32
|
+
# remove(list_key, options)
|
33
|
+
#
|
34
|
+
# === Options
|
35
|
+
#
|
36
|
+
# +leads+:: Required. An array of Lead objects or lead keys. If both
|
37
|
+
# +leads+ and +lead+ are provided, they will be merged.
|
38
|
+
# +lead+:: An alias for +leads+.
|
39
|
+
# +strict+:: If +true+, the entire operation fails if any subset fails.
|
40
|
+
# Non-strict mode will complete everything it can and return
|
41
|
+
# errors for anything that failed.
|
42
|
+
#
|
43
|
+
# Add leads to a Marketo list.
|
44
|
+
|
45
|
+
##
|
46
|
+
# :method: member?
|
47
|
+
# :call-seq:
|
48
|
+
# member?(list_key, options)
|
49
|
+
#
|
50
|
+
# === Options
|
51
|
+
#
|
52
|
+
# +leads+:: Required. An array of Lead objects or lead keys. If both
|
53
|
+
# +leads+ and +lead+ are provided, they will be merged.
|
54
|
+
# +lead+:: An alias for +leads+.
|
55
|
+
# +strict+:: If +true+, the entire operation fails if any subset fails.
|
56
|
+
# Non-strict mode will complete everything it can and return
|
57
|
+
# errors for anything that failed.
|
58
|
+
#
|
59
|
+
# Add leads to a Marketo list.
|
60
|
+
|
61
|
+
{
|
62
|
+
add: :ADDTOLIST,
|
63
|
+
remove: :REMOVEFROMLIST,
|
64
|
+
member?: :ISMEMBEROFLIST,
|
65
|
+
}.each do |name, operation|
|
66
|
+
define_method(name) do |list_key, options = {}|
|
67
|
+
list_operation(operation, list_key, options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
def key(type, value)
|
73
|
+
{
|
74
|
+
list_key: {
|
75
|
+
key_type: key_type(type),
|
76
|
+
key_value: value
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
def key_type(key)
|
83
|
+
res = if TYPES.include? key
|
84
|
+
key
|
85
|
+
else
|
86
|
+
NAMED_TYPES[key]
|
87
|
+
end
|
88
|
+
raise ArgumentError, "Invalid key #{key}" unless res
|
89
|
+
res
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
def list_operation(operation, list_key, options = {})
|
95
|
+
leads = MarketoAPI.array(options.delete(:leads)) +
|
96
|
+
MarketoAPI.array(options.delete(:lead))
|
97
|
+
if leads.empty?
|
98
|
+
raise ArgumentError, ':lead or :leads must be provided'
|
99
|
+
end
|
100
|
+
|
101
|
+
call(
|
102
|
+
:list_operation,
|
103
|
+
list_operation: operation,
|
104
|
+
list_key: list_key,
|
105
|
+
strict: false,
|
106
|
+
list_member_list: transform_param_list(:get, leads)
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,272 @@
|
|
1
|
+
# A representation of Marketo object (MObject) records as well as key
|
2
|
+
# representations for getting, syncing, or deleting those records.
|
3
|
+
class MarketoAPI::MObject
|
4
|
+
DELETE_TYPES = #:nodoc:
|
5
|
+
MarketoAPI.freeze(:Opportunity, :OpportunityPersonRole)
|
6
|
+
GET_TYPES = #:nodoc:
|
7
|
+
MarketoAPI.freeze(*DELETE_TYPES, :Program)
|
8
|
+
DESCRIBE_TYPES = #:nodoc:
|
9
|
+
MarketoAPI.freeze(*DELETE_TYPES, :ActivityRecord, :LeadRecord )
|
10
|
+
ALL_TYPES = #:nodoc:
|
11
|
+
MarketoAPI.freeze(*[ GET_TYPES, DESCRIBE_TYPES ].flatten.uniq)
|
12
|
+
|
13
|
+
# The type of Marketo object. Will be one of:
|
14
|
+
#
|
15
|
+
# - Opportunity
|
16
|
+
# - OpportunityPersonRole
|
17
|
+
# - Program
|
18
|
+
# - ActivityRecord
|
19
|
+
# - LeadRecord
|
20
|
+
#
|
21
|
+
# In general, only the first three can be interacted with through the SOAP
|
22
|
+
# API.
|
23
|
+
attr_reader :type
|
24
|
+
# The ID of the Marketo object.
|
25
|
+
attr_accessor :id
|
26
|
+
|
27
|
+
# Associated objects.
|
28
|
+
attr_reader :associations
|
29
|
+
# The stream position for paged queries.
|
30
|
+
attr_accessor :stream_position
|
31
|
+
|
32
|
+
##
|
33
|
+
# :attr_accessor: include_details
|
34
|
+
# When getting a Marketo Program, the details will be included if this is
|
35
|
+
# +true+.
|
36
|
+
|
37
|
+
# The detailed attributes of the Marketo object.
|
38
|
+
attr_reader :attributes
|
39
|
+
# The detailed types of the Marketo object.
|
40
|
+
attr_reader :types
|
41
|
+
|
42
|
+
def initialize(type, id = nil)
|
43
|
+
@type = ensure_valid_type!(type)
|
44
|
+
@id = id
|
45
|
+
@attributes = {}
|
46
|
+
@criteria = []
|
47
|
+
@associations = []
|
48
|
+
@stream_position = nil
|
49
|
+
@include_details = false
|
50
|
+
@types = Hash.new { |h, k| h[k] = {} }
|
51
|
+
yield self if block_given?
|
52
|
+
end
|
53
|
+
|
54
|
+
def include_details
|
55
|
+
@include_details
|
56
|
+
end
|
57
|
+
|
58
|
+
def include_details=(value) #:nodoc:
|
59
|
+
@include_details= !!value
|
60
|
+
end
|
61
|
+
|
62
|
+
# Adds query criteria for use with MarketoAPI::MObjects#get.
|
63
|
+
#
|
64
|
+
# === Name
|
65
|
+
#
|
66
|
+
# Name:: Name of the MObject
|
67
|
+
# Role:: The role associated with an
|
68
|
+
# OpportunityPersonRole object
|
69
|
+
# Type:: The type of an Opportunity object
|
70
|
+
# Stage:: The stage of an Opportunity object
|
71
|
+
# CRM Id: The CRM ID could refer to the ID of the
|
72
|
+
# Salesforce campaign connected to a Marketo
|
73
|
+
# program
|
74
|
+
# Created At:: The date the MObject was created. Can be used
|
75
|
+
# with the comparisons EQ, NE, LT, LE, GT, and
|
76
|
+
# GE. Two “created dates” can be specified to
|
77
|
+
# create a date range.
|
78
|
+
# Updated At or Tag Type:: (Only one can be specified) Can be used with
|
79
|
+
# the comparisons EQ, NE, LT, LE, GT, and GE. Two
|
80
|
+
# “updated dates” can be specified to create a
|
81
|
+
# date range.
|
82
|
+
# Tag Value: (Only one can be specified)
|
83
|
+
# Workspace Name: (Only one can be specified)
|
84
|
+
# Workspace Id: (Only one can be specified)
|
85
|
+
# Include Archive: Applicable only with Program MObject. Set it to
|
86
|
+
# true if you wish to include archived programs.
|
87
|
+
#
|
88
|
+
# === Comparison
|
89
|
+
#
|
90
|
+
# EQ:: Equals
|
91
|
+
# NE:: Not Equals
|
92
|
+
# LT:: Less Than
|
93
|
+
# LE:: Less Than or Equals
|
94
|
+
# GT:: Greater Than
|
95
|
+
# GE:: Greater Than or Equals
|
96
|
+
def criteria(name = nil, value = nil, comparison = nil)
|
97
|
+
@criteria << Criteria.new(name, value, comparison) if name
|
98
|
+
@criteria
|
99
|
+
end
|
100
|
+
|
101
|
+
# Add association criteria for use with MarketoAPI::MObjects#get or
|
102
|
+
# MarketoAPI::MOBjects#sync (not yet implemented).
|
103
|
+
#
|
104
|
+
# Type +type+ must be one of +Lead+, +Company+, or +Opportunity+. It must
|
105
|
+
# be accompanied with one of the following parameters:
|
106
|
+
#
|
107
|
+
# id:: The Marketo ID of the associated object.
|
108
|
+
# external:: The custom attribute value of the associated object. Can
|
109
|
+
# also be accessed as +external_key+.
|
110
|
+
def association(type, options = {})
|
111
|
+
@associations << Association.new(type, options)
|
112
|
+
@associations
|
113
|
+
end
|
114
|
+
|
115
|
+
def params_for_delete #:nodoc:
|
116
|
+
ensure_valid_type!(type, DELETE_TYPES)
|
117
|
+
raise ArgumentError, ":id cannot be nil" if id.nil?
|
118
|
+
{ type: type, id: id }
|
119
|
+
end
|
120
|
+
|
121
|
+
def params_for_get #:nodoc:
|
122
|
+
ensure_valid_type!(type, GET_TYPES)
|
123
|
+
{
|
124
|
+
type: type,
|
125
|
+
id: id,
|
126
|
+
include_details: include_details,
|
127
|
+
m_obj_criteria_list: criteria.compact.uniq.map(&:to_h),
|
128
|
+
m_obj_association_list: associations.compact.uniq.map(&:to_h),
|
129
|
+
stream_position: stream_position
|
130
|
+
}.delete_if(&MarketoAPI::MINIMIZE_HASH)
|
131
|
+
end
|
132
|
+
|
133
|
+
def ==(other)
|
134
|
+
type == other.type &&
|
135
|
+
include_details == other.include_details &&
|
136
|
+
id == other.id &&
|
137
|
+
stream_position == other.stream_position &&
|
138
|
+
attributes == other.attributes &&
|
139
|
+
types == other.types &&
|
140
|
+
criteria == other.criteria &&
|
141
|
+
associations == other.associations
|
142
|
+
end
|
143
|
+
|
144
|
+
class << self
|
145
|
+
# Creates a new MObject from a SOAP response hash (from MObjects#get or
|
146
|
+
# MObjects#sync).
|
147
|
+
def from_soap_hash(hash) #:nodoc:
|
148
|
+
new(hash[:type], hash[:id]) do |mobj|
|
149
|
+
obj = hash[:attrib_list][:attrib]
|
150
|
+
MarketoAPI.array(obj).each do |attrib|
|
151
|
+
mobj.attributes[attrib[:name].to_sym] = attrib[:value]
|
152
|
+
end
|
153
|
+
|
154
|
+
obj = hash[:type_attrib_list][:type_attrib]
|
155
|
+
MarketoAPI.array(obj).each do |type|
|
156
|
+
MarketoAPI.array(type[:attr_list][:attrib]).each do |attrib|
|
157
|
+
mobj.types[type[:attr_type].to_sym][attrib[:name].to_sym] =
|
158
|
+
attrib[:value]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
ALL_TYPES.each do |type|
|
165
|
+
define_method(type.downcase) do |id = nil, &block|
|
166
|
+
new(type, id, &block)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class Criteria #:nodoc:
|
172
|
+
TYPES = { #:nodoc:
|
173
|
+
name: "Name",
|
174
|
+
role: "Role",
|
175
|
+
type: "Type",
|
176
|
+
stage: "Stage",
|
177
|
+
crm_id: "CRM Id",
|
178
|
+
created_at: "Created At",
|
179
|
+
updated_at: "Updated At",
|
180
|
+
tag_type: "Tag Type",
|
181
|
+
tag_value: "Tag Value",
|
182
|
+
workspace_name: "Workspace Name",
|
183
|
+
workspace_id: "Workspace Id",
|
184
|
+
include_archive: "Include Archive"
|
185
|
+
}.freeze
|
186
|
+
TYPES.values.map(&:freeze)
|
187
|
+
|
188
|
+
CMP = [ #:nodoc:
|
189
|
+
:EQ, :NE, :LT, :LE, :GT, :GE
|
190
|
+
]
|
191
|
+
|
192
|
+
attr_reader :name, :value, :comparison
|
193
|
+
|
194
|
+
def initialize(name, value, comparison)
|
195
|
+
name = if TYPES.has_key?(name.to_sym)
|
196
|
+
TYPES[name.to_sym]
|
197
|
+
elsif TYPES.values.include?(name)
|
198
|
+
TYPES.values[TYPES.values.index(name)]
|
199
|
+
else
|
200
|
+
raise ArgumentError, "Invalid type name [#{name}]"
|
201
|
+
end
|
202
|
+
|
203
|
+
unless CMP.include?(comparison.to_s.to_sym.upcase)
|
204
|
+
raise ArgumentError, "Invalid comparison [#{comparison}]"
|
205
|
+
end
|
206
|
+
|
207
|
+
@name, @value, @comparison = name, value, comparison.to_sym.upcase
|
208
|
+
end
|
209
|
+
|
210
|
+
def ==(other)
|
211
|
+
name.equal?(other.name) && comparison.equal?(other.comparison) &&
|
212
|
+
value == other.value?
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_h
|
216
|
+
{
|
217
|
+
attr_name: name,
|
218
|
+
attr_value: value,
|
219
|
+
comparison: comparison
|
220
|
+
}
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class Association #:nodoc:
|
225
|
+
TYPES = [ #:nodoc:
|
226
|
+
:Lead, :Company, :Opportunity
|
227
|
+
]
|
228
|
+
|
229
|
+
attr_reader :type, :id, :external_key
|
230
|
+
alias_method :external, :external_key
|
231
|
+
|
232
|
+
def initialize(type, options = {})
|
233
|
+
unless TYPES.include?(type.to_s.capitalize.to_sym)
|
234
|
+
raise ArgumentError, "Invalid type #{type}"
|
235
|
+
end
|
236
|
+
|
237
|
+
@type = TYPES[TYPES.index(type.to_s.capitalize.to_sym)]
|
238
|
+
|
239
|
+
options.fetch(:id) {
|
240
|
+
options.fetch(:external) {
|
241
|
+
options.fetch(:external_key) {
|
242
|
+
raise KeyError, "Must have one of :id or :external"
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
@id = options[:id]
|
248
|
+
@external_key = options[:external] || options[:external_key]
|
249
|
+
end
|
250
|
+
|
251
|
+
def ==(other)
|
252
|
+
type.equal?(other.type) && id == other.id &&
|
253
|
+
external_key == other.external_key
|
254
|
+
end
|
255
|
+
|
256
|
+
def to_h
|
257
|
+
{
|
258
|
+
m_obj_type: type,
|
259
|
+
id: id,
|
260
|
+
external_key: external_key,
|
261
|
+
}
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
def ensure_valid_type!(type, list = ALL_TYPES)
|
267
|
+
unless list.include? type.to_sym
|
268
|
+
raise ArgumentError, ":type must be one of #{list.join(", ")}"
|
269
|
+
end
|
270
|
+
type.to_sym
|
271
|
+
end
|
272
|
+
end
|