riq 0.8.3
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 +7 -0
- data/.gitignore +41 -0
- data/.yardopts +2 -0
- data/Gemfile +8 -0
- data/lib/relateiq.rb +3 -0
- data/lib/relateiq/account.rb +79 -0
- data/lib/relateiq/batch_manager.rb +187 -0
- data/lib/relateiq/client.rb +152 -0
- data/lib/relateiq/contact.rb +139 -0
- data/lib/relateiq/error.rb +53 -0
- data/lib/relateiq/events.rb +104 -0
- data/lib/relateiq/list.rb +87 -0
- data/lib/relateiq/list_item_manager.rb +13 -0
- data/lib/relateiq/listitem.rb +115 -0
- data/lib/relateiq/riq_obj.rb +142 -0
- data/lib/relateiq/user.rb +36 -0
- data/test/test.rb +4 -0
- data/test/test_account.rb +39 -0
- data/test/test_batch_manager.rb +45 -0
- data/test/test_contact.rb +50 -0
- metadata +96 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
require_relative 'riq_obj'
|
2
|
+
|
3
|
+
module RIQ
|
4
|
+
class Contact < RIQObject
|
5
|
+
attr_accessor :properties
|
6
|
+
|
7
|
+
# (see RIQObject#node)
|
8
|
+
def node
|
9
|
+
self.class.node(@id)
|
10
|
+
end
|
11
|
+
|
12
|
+
# (see RIQObject#node)
|
13
|
+
def self.node(id = nil)
|
14
|
+
"contacts/#{id}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# (see RIQObject#data)
|
18
|
+
def data
|
19
|
+
{
|
20
|
+
id: @id,
|
21
|
+
properties: @properties
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# @!macro [new] prop
|
26
|
+
# @return [Array] all of the values for $0
|
27
|
+
def name
|
28
|
+
get_prop(:name)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @macro prop
|
32
|
+
def phone
|
33
|
+
get_prop(:phone)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @macro prop
|
37
|
+
def email
|
38
|
+
get_prop(:email)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @macro prop
|
42
|
+
def address
|
43
|
+
get_prop(:address)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Adds property with correct scaffolding
|
47
|
+
# @param prop [Symbol] Type Property to add, such as :name or :email
|
48
|
+
# @param val [String, Array] Value(s) to add
|
49
|
+
# @return [Array] Values for that property after the add
|
50
|
+
def add(prop, val)
|
51
|
+
# validate(prop)
|
52
|
+
prop = prop.to_sym
|
53
|
+
@properties[prop] = [] unless @properties.include? prop
|
54
|
+
|
55
|
+
if val.is_a? Array
|
56
|
+
val.each do |i|
|
57
|
+
add(prop, i)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# don't add duplicate
|
62
|
+
if @properties[prop].select{|p| p[:value] == val}.empty?
|
63
|
+
@properties[prop] << {value: val, metadata: {}}
|
64
|
+
end
|
65
|
+
send(prop)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Removes property from hash
|
69
|
+
# @param prop [Symbol] Type Property to remove, such as :name or :email
|
70
|
+
# @param val [String, Array] Value(s) to remove
|
71
|
+
# @return [Array] Values for that property after the remove
|
72
|
+
def remove(prop, val)
|
73
|
+
# validate(prop)
|
74
|
+
prop = prop.to_sym
|
75
|
+
|
76
|
+
if val.is_a? Array
|
77
|
+
val.each do |i|
|
78
|
+
remove(prop, i)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if @properties.include? prop
|
83
|
+
@properties[prop] = @properties[prop].reject{|p| p[:value] == val}
|
84
|
+
end
|
85
|
+
send(prop)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Edits an existing object based on matching email(s) or saves a new object
|
89
|
+
# @see RIQObject#save
|
90
|
+
def upsert
|
91
|
+
save({_upsert: 'email'})
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param prop [Symbol] The property to fetch. One of [:name, :phone, :email, :address]
|
95
|
+
# @param val [String] The value to get info on, such as 'name@domain.com'
|
96
|
+
# @return [Hash] metadata and other info about a given property
|
97
|
+
def info(prop, val)
|
98
|
+
# validate(prop)
|
99
|
+
|
100
|
+
@properties[prop].select{|p| p[:value] == val}.first
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def init(obj = nil)
|
106
|
+
unless obj.nil?
|
107
|
+
@id = obj['id']
|
108
|
+
@properties = symbolize(obj['properties'])
|
109
|
+
else
|
110
|
+
@id = nil
|
111
|
+
@properties = {}
|
112
|
+
end
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# unused because we actually put all sorts of stuff in there
|
117
|
+
def validate(prop)
|
118
|
+
raise RIQError, %q(Invalid property. Use [:name | :phone | :email | :address] instead) unless [:name, :phone, :email, :address].include? prop
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_prop(prop)
|
122
|
+
if @properties.include? prop
|
123
|
+
@properties[prop].map{|p| p[:value]}
|
124
|
+
else
|
125
|
+
[]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class << self
|
131
|
+
# Convenince method to create new Contacts
|
132
|
+
# @param id [String, nil] create a blank Contact object or
|
133
|
+
# fetch an existing one by id.
|
134
|
+
# @return [RIQ::Contact]
|
135
|
+
def contact(id = nil)
|
136
|
+
Contact.new(id)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Base exception class for our errors
|
2
|
+
|
3
|
+
module RIQ
|
4
|
+
class RIQError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class NotImplementedError < RIQError
|
8
|
+
end
|
9
|
+
|
10
|
+
class NotFoundError < RIQError
|
11
|
+
end
|
12
|
+
|
13
|
+
class HTTPError < RIQError
|
14
|
+
attr_accessor :code
|
15
|
+
attr_accessor :message
|
16
|
+
attr_accessor :response
|
17
|
+
|
18
|
+
def initialize(resp)
|
19
|
+
# build response message
|
20
|
+
message = "\n[#{resp.code}] #{resp.message} : "
|
21
|
+
unless resp.parsed_response.nil?
|
22
|
+
begin
|
23
|
+
m = resp.parsed_response.fetch('errorMessage', 'no message')
|
24
|
+
rescue
|
25
|
+
# parse returned html
|
26
|
+
reg = resp.parsed_response.match(/<pre>(.*)<\/pre>/)
|
27
|
+
unless reg.nil?
|
28
|
+
m = reg[1].strip
|
29
|
+
else
|
30
|
+
m = 'no message'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
message += "<#{m}>"
|
34
|
+
end
|
35
|
+
|
36
|
+
# pull out request info
|
37
|
+
req = resp.request
|
38
|
+
unless req.nil?
|
39
|
+
message += "\n Request: #{req.http_method} #{req.last_uri.to_s}"
|
40
|
+
unless req.raw_body.nil?
|
41
|
+
message += "\n #{req.raw_body}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@message = message
|
46
|
+
@response = resp
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
@message || super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# require 'set'
|
2
|
+
# require 'json'
|
3
|
+
# require_relative 'riq_base'
|
4
|
+
|
5
|
+
# # Events.rb
|
6
|
+
# # Events represent interactions involving a Contact associated with a List Item.
|
7
|
+
# # Instead of appearing as new content in List columns, Events appear in a “Stream view”
|
8
|
+
# # associated with the appropriate List Item. If the same Contact is associated
|
9
|
+
# # with more than one List Item, then the Event will appear in all relevant Stream views.
|
10
|
+
# # For more info visit https://api.relateiq.com/#/ruby
|
11
|
+
|
12
|
+
# class Event < RIQBase
|
13
|
+
# # Object Attributes
|
14
|
+
# @id = nil
|
15
|
+
# @modifiedDate = nil
|
16
|
+
# @participantIds = nil
|
17
|
+
# @subject = nil
|
18
|
+
# @body = nil
|
19
|
+
|
20
|
+
# def initialize(
|
21
|
+
# _id=nil,
|
22
|
+
# subject=nil,
|
23
|
+
# body=nil,
|
24
|
+
# participantIds=nil,
|
25
|
+
# data:nil,
|
26
|
+
# hash:nil
|
27
|
+
# )
|
28
|
+
# if !data.nil?
|
29
|
+
# parse(data)
|
30
|
+
# elsif !hash.nil?
|
31
|
+
# process_hash(hash)
|
32
|
+
# elsif !id(_id).nil?
|
33
|
+
# Event::get(self)
|
34
|
+
# end
|
35
|
+
# participantIds(participantIds)
|
36
|
+
# subject(subject)
|
37
|
+
# body(body)
|
38
|
+
# end
|
39
|
+
|
40
|
+
# class << self
|
41
|
+
# def node
|
42
|
+
# 'events'
|
43
|
+
# end
|
44
|
+
|
45
|
+
# def factory(data = nil, hash = nil)
|
46
|
+
# return Event.new(data, hash)
|
47
|
+
# end
|
48
|
+
|
49
|
+
# def update(instance, options = {})
|
50
|
+
# response = Client::put(self.endpoint(), instance.payload(), options)
|
51
|
+
# return instance
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
|
55
|
+
# def parse(data)
|
56
|
+
# obj = JSON.parse(data.body)
|
57
|
+
# id(obj['id'])
|
58
|
+
# modifiedDate(obj['modifiedDate'])
|
59
|
+
# end
|
60
|
+
|
61
|
+
# def process_hash(hash)
|
62
|
+
# id(hash['id'])
|
63
|
+
# modifiedDate(hash['modifiedDate'])
|
64
|
+
# end
|
65
|
+
|
66
|
+
# # Data Payload
|
67
|
+
# def payload()
|
68
|
+
# payload = {:participantIds => @participantIds,
|
69
|
+
# :subject => subject(),
|
70
|
+
# :body => body()
|
71
|
+
# }
|
72
|
+
# if modifiedDate() then
|
73
|
+
# payload['modifiedDate'] = modifiedDate()
|
74
|
+
# end
|
75
|
+
# payload['id'] = id() if id()
|
76
|
+
# return payload
|
77
|
+
# end
|
78
|
+
|
79
|
+
# # Hybrid
|
80
|
+
# def id(value = nil)
|
81
|
+
# @id = value unless value.nil?
|
82
|
+
# end
|
83
|
+
|
84
|
+
# def modifiedDate(value = nil)
|
85
|
+
# @modifiedDate = value unless value.nil?
|
86
|
+
# end
|
87
|
+
|
88
|
+
# def subject(value = nil)
|
89
|
+
# @subject = value unless value.nil?
|
90
|
+
# end
|
91
|
+
|
92
|
+
# # value should either be a string or a list of strings
|
93
|
+
# # returns: if multiple values exist for key, a list of strings of values
|
94
|
+
# # if a single value exists, return the single string value (not in a list)
|
95
|
+
# # if no values exist, return nil
|
96
|
+
# def participantIds(value = nil)
|
97
|
+
# # set value if passed in
|
98
|
+
# @participantIds = value unless value.nil?
|
99
|
+
# end
|
100
|
+
|
101
|
+
# def body(value=nil)
|
102
|
+
# @body = value unless value.nil?
|
103
|
+
# end
|
104
|
+
# end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# require_relative 'riq_obj'
|
2
|
+
# require_relative 'batch_manager'
|
3
|
+
|
4
|
+
module RIQ
|
5
|
+
class List < RIQObject
|
6
|
+
# can't create a list through api, so these don't need to write
|
7
|
+
attr_reader :title
|
8
|
+
attr_reader :type
|
9
|
+
attr_reader :list_items
|
10
|
+
# for consistency
|
11
|
+
alias_method :name, :title
|
12
|
+
|
13
|
+
# (see RIQObject#initialize)
|
14
|
+
def initialize(id = nil)
|
15
|
+
super
|
16
|
+
@list_items = ListItemManager.new(@id)
|
17
|
+
end
|
18
|
+
|
19
|
+
# (see RIQObject#node)
|
20
|
+
def node
|
21
|
+
self.class.node(@id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# (see RIQObject#node)
|
25
|
+
def self.node(id = nil)
|
26
|
+
"lists/#{id}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# (see RIQObject#data)
|
30
|
+
def data
|
31
|
+
{
|
32
|
+
id: @id,
|
33
|
+
title: @title,
|
34
|
+
type: @type,
|
35
|
+
fields: @fields
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Overwriting parent because litsts can't be saved through the API
|
40
|
+
def save
|
41
|
+
raise NotImplementedError, "Lists can't be edited through the API"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Gets field if it exists
|
45
|
+
# @param id [String, Integer] field ID
|
46
|
+
# @return [Hash, nil] info on the field specified
|
47
|
+
def fields(id = nil)
|
48
|
+
unless id.nil?
|
49
|
+
@fields.select{|f| f['id'] == id.to_s}.first
|
50
|
+
else
|
51
|
+
@fields
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def list_item(oid = nil)
|
56
|
+
RIQ::ListItem.new(oid, lid: @id)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def init(obj = nil)
|
62
|
+
unless obj.nil?
|
63
|
+
@id = obj['id']
|
64
|
+
@title = obj['title']
|
65
|
+
@type = obj['listType']
|
66
|
+
@fields = obj['fields']
|
67
|
+
else
|
68
|
+
@id = nil
|
69
|
+
@title = nil
|
70
|
+
@type = nil
|
71
|
+
@fields = nil
|
72
|
+
end
|
73
|
+
self
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class << self
|
78
|
+
# Convenince method to create new Lists
|
79
|
+
# @param id [String, nil] create a blank List object or
|
80
|
+
# fetch an existing one by id.
|
81
|
+
# @return [List]
|
82
|
+
def list(id = nil)
|
83
|
+
List.new(id)
|
84
|
+
end
|
85
|
+
# TODO: could also just have #lists that returns whatever i'm supposed to be returning for my generator
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module RIQ
|
4
|
+
class ListItem < RIQObject
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :field_values
|
7
|
+
attr_accessor :account_id
|
8
|
+
attr_accessor :contact_ids
|
9
|
+
attr_accessor :list_id
|
10
|
+
|
11
|
+
attr_reader :modified_date
|
12
|
+
attr_reader :created_date
|
13
|
+
|
14
|
+
def initialize(id = nil, lid: nil)
|
15
|
+
if id.is_a? Hash
|
16
|
+
super(id)
|
17
|
+
elsif id.nil? && lid.nil?
|
18
|
+
super(nil)
|
19
|
+
elsif id.nil? && !lid.nil?
|
20
|
+
super(nil)
|
21
|
+
@list_id = lid
|
22
|
+
elsif id.nil? || lid.nil?
|
23
|
+
raise RIQError, 'ObjectID and List ID are required'
|
24
|
+
else
|
25
|
+
super("#{lid}/listitems/#{id}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# (see RIQObject#node)
|
30
|
+
def node
|
31
|
+
self.class.node(@list_id, @id)
|
32
|
+
end
|
33
|
+
|
34
|
+
# (see #node)
|
35
|
+
def self.node(lid = nil, oid = nil)
|
36
|
+
# weird workaround for fetching node on init
|
37
|
+
if lid.nil? && !oid.nil?
|
38
|
+
"lists/#{oid}"
|
39
|
+
else
|
40
|
+
"lists/#{lid || @list_id}/listitems/#{oid}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# (see RIQObject#data)
|
45
|
+
def data
|
46
|
+
{
|
47
|
+
name: @name,
|
48
|
+
account_id: @account_id,
|
49
|
+
contact_ids: @contact_ids.flatten,
|
50
|
+
id: @id,
|
51
|
+
list_id: @list_id,
|
52
|
+
field_values: @field_values,
|
53
|
+
modified_date: @modified_date
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# (see RIQObject#payload)
|
58
|
+
def payload
|
59
|
+
pld = {}
|
60
|
+
data.each do |k, v|
|
61
|
+
if k == :field_values
|
62
|
+
pld['fieldValues'] = to_raw(@field_values)
|
63
|
+
elsif k['_']
|
64
|
+
pld[camel_case(k)] = v
|
65
|
+
else
|
66
|
+
pld[k] = v
|
67
|
+
end
|
68
|
+
end
|
69
|
+
pld.to_json
|
70
|
+
end
|
71
|
+
|
72
|
+
# @overload field_value(key)
|
73
|
+
# @param key [String, Integer]
|
74
|
+
# @return [Array] Value of key
|
75
|
+
# @overload field_value(key, value)
|
76
|
+
# Sets key to value
|
77
|
+
# @param key [String, Integer] Key to set
|
78
|
+
# @param value [#to_s] Sets key to value
|
79
|
+
def field_value(key, value = nil)
|
80
|
+
# TODO: double check that this works with arrays of stuff
|
81
|
+
# or, have a format function that casts ints to string on save
|
82
|
+
if value.nil?
|
83
|
+
@field_values.fetch(key.to_s, nil)
|
84
|
+
else
|
85
|
+
@field_values[key.to_s] = value.to_s
|
86
|
+
{key.to_s => value.to_s}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def init(obj = nil)
|
93
|
+
unless obj.nil?
|
94
|
+
@id = obj['id']
|
95
|
+
@list_id = obj['listId']
|
96
|
+
@name = obj['name']
|
97
|
+
@field_values = from_raw(obj['fieldValues'])
|
98
|
+
@account_id = obj['accountId']
|
99
|
+
@contact_ids = obj['contactIds']
|
100
|
+
@modified_date = obj['modifiedDate']
|
101
|
+
@created_date = obj['creaetedDate']
|
102
|
+
else
|
103
|
+
@id = nil
|
104
|
+
@list_id = nil
|
105
|
+
@name = nil
|
106
|
+
@field_values = {}
|
107
|
+
@account_id = nil
|
108
|
+
@contact_ids = []
|
109
|
+
@modified_date = nil
|
110
|
+
@created_date = nil
|
111
|
+
end
|
112
|
+
self
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|