riq 1.0.1 → 1.0.2
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/.gitignore +42 -0
- data/.yardopts +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +33 -0
- data/lib/riq.rb +103 -0
- data/lib/riq/account.rb +82 -0
- data/lib/riq/batch_manager.rb +133 -0
- data/lib/riq/client.rb +130 -0
- data/lib/riq/contact.rb +158 -0
- data/lib/riq/error.rb +56 -0
- data/lib/riq/event.rb +73 -0
- data/lib/riq/list.rb +89 -0
- data/lib/riq/list_item.rb +119 -0
- data/lib/riq/list_item_manager.rb +13 -0
- data/lib/riq/riq_obj.rb +105 -0
- data/lib/riq/user.rb +47 -0
- data/riq.gemspec +29 -0
- data/test/test.rb +4 -0
- data/test/test_account.rb +44 -0
- data/test/test_batch_manager.rb +72 -0
- data/test/test_contact.rb +62 -0
- data/test/test_event.rb +56 -0
- data/test/test_list_item.rb +42 -0
- metadata +33 -3
data/lib/riq/contact.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require_relative 'riq_obj'
|
2
|
+
using RIQExtensions
|
3
|
+
|
4
|
+
module RIQ
|
5
|
+
# Contacts represent people in an Organization’s address book.
|
6
|
+
class Contact < RIQObject
|
7
|
+
attr_accessor :properties
|
8
|
+
|
9
|
+
# (see RIQObject#node)
|
10
|
+
def node
|
11
|
+
self.class.node(@id)
|
12
|
+
end
|
13
|
+
|
14
|
+
# (see RIQObject.node)
|
15
|
+
def self.node(id = nil)
|
16
|
+
"contacts/#{id}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# (see RIQObject#data)
|
20
|
+
def data
|
21
|
+
{
|
22
|
+
id: @id,
|
23
|
+
properties: @properties
|
24
|
+
# modified_date: @modified_date
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!macro [new] prop
|
29
|
+
# @return [Array] all of the values for $0
|
30
|
+
def name
|
31
|
+
get_prop(:name)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @macro prop
|
35
|
+
def phone
|
36
|
+
get_prop(:phone)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @macro prop
|
40
|
+
def email
|
41
|
+
get_prop(:email)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @macro prop
|
45
|
+
def address
|
46
|
+
get_prop(:address)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Adds property with correct scaffolding
|
50
|
+
# @param prop [Symbol] Type Property to add, such as :name or :email
|
51
|
+
# @param val [String, Array] Value(s) to add
|
52
|
+
# @return [Array] Values for that property after the add
|
53
|
+
def add(prop, val)
|
54
|
+
# validate(prop)
|
55
|
+
prop = prop.to_sym
|
56
|
+
@properties[prop] = [] unless @properties.include? prop
|
57
|
+
|
58
|
+
if val.is_a? Array
|
59
|
+
val.each do |i|
|
60
|
+
add(prop, i)
|
61
|
+
end
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
raise RIQError, 'Values must be strings' unless val.is_a? String
|
66
|
+
|
67
|
+
# don't add duplicate
|
68
|
+
if @properties[prop].select{|p| p[:value] == val}.empty?
|
69
|
+
@properties[prop] << {value: val, metadata: {}}
|
70
|
+
end
|
71
|
+
send(prop)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Removes property from hash
|
75
|
+
# @param prop [Symbol] Type Property to remove, such as :name or :email
|
76
|
+
# @param val [String, Array] Value(s) to remove
|
77
|
+
# @return [Array] Values for that property after the remove
|
78
|
+
def remove(prop, val)
|
79
|
+
# validate(prop)
|
80
|
+
prop = prop.to_sym
|
81
|
+
|
82
|
+
if val.is_a? Array
|
83
|
+
val.each do |i|
|
84
|
+
remove(prop, i)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if @properties.include? prop
|
89
|
+
@properties[prop] = @properties[prop].reject{|p| p[:value] == val}
|
90
|
+
end
|
91
|
+
send(prop)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Edits an existing object based on matching email(s) or saves a new object
|
95
|
+
# @see RIQObject#save
|
96
|
+
def upsert
|
97
|
+
save({_upsert: 'email'})
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param prop [Symbol] The property to fetch. One of [:name, :phone, :email, :address]
|
101
|
+
# @param val [String] The value to get info on, such as 'name@domain.com'
|
102
|
+
# @return [Hash] metadata and other info about a given property
|
103
|
+
def info(prop, val)
|
104
|
+
# validate(prop)
|
105
|
+
|
106
|
+
@properties[prop].select{|p| p[:value] == val}.first
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def init(obj = nil)
|
112
|
+
unless obj.nil?
|
113
|
+
@id = obj[:id]
|
114
|
+
@modified_date = obj[:modified_date].cut_milis if obj[:modified_date]
|
115
|
+
@properties = {}
|
116
|
+
obj[:properties].each do |k,v|
|
117
|
+
raise RIQError, "Properties must be arrays, #{k} wasn't" if !v.is_a?(Array)
|
118
|
+
|
119
|
+
v.each do |i|
|
120
|
+
unless i.is_a?(Hash)
|
121
|
+
add(k, i)
|
122
|
+
else
|
123
|
+
@properties[k] = [] unless @properties.include?(k)
|
124
|
+
@properties[k] << i
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
else
|
129
|
+
@id = nil
|
130
|
+
@properties = {}
|
131
|
+
end
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
# unused because we actually put all sorts of stuff in there
|
136
|
+
def validate(prop)
|
137
|
+
raise RIQError, %q(Invalid property. Use [:name | :phone | :email | :address] instead) unless [:name, :phone, :email, :address].include? prop
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_prop(prop)
|
141
|
+
if @properties.include? prop
|
142
|
+
@properties[prop].map{|p| p[:value]}
|
143
|
+
else
|
144
|
+
[]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class << self
|
150
|
+
# Convenience method to create new Contacts
|
151
|
+
# @param id [String, nil] create a blank Contact object or
|
152
|
+
# fetch an existing one by id.
|
153
|
+
# @return [Contact]
|
154
|
+
def contact(id = nil)
|
155
|
+
Contact.new(id)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/riq/error.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module RIQ
|
2
|
+
# Base exception class for our errors.
|
3
|
+
class RIQError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
# Hasn't been implemented yet. Doesn't get used often.
|
7
|
+
class NotImplementedError < RIQError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Raised when an ObjectId fetch doesn't return anything.
|
11
|
+
class NotFoundError < RIQError
|
12
|
+
end
|
13
|
+
|
14
|
+
# Main error that includes info about the request and what went wrong.
|
15
|
+
class HTTPError < RIQError
|
16
|
+
attr_accessor :code
|
17
|
+
attr_accessor :message
|
18
|
+
attr_accessor :response
|
19
|
+
|
20
|
+
def initialize(resp)
|
21
|
+
# build response message
|
22
|
+
message = "\n[#{resp.code}] #{resp.message} : "
|
23
|
+
unless resp.parsed_response.nil?
|
24
|
+
begin
|
25
|
+
m = resp.parsed_response.fetch('errorMessage', 'no message')
|
26
|
+
rescue
|
27
|
+
# parse returned HTML
|
28
|
+
reg = resp.parsed_response.match(/<pre>(.*)<\/pre>/)
|
29
|
+
unless reg.nil?
|
30
|
+
m = reg[1].strip
|
31
|
+
else
|
32
|
+
m = 'no message'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
message += "<#{m}>"
|
36
|
+
end
|
37
|
+
|
38
|
+
# pull out request info
|
39
|
+
req = resp.request
|
40
|
+
unless req.nil?
|
41
|
+
message += "\n Request: #{req.http_method} #{req.last_uri.to_s}"
|
42
|
+
unless req.raw_body.nil?
|
43
|
+
message += "\n #{req.raw_body}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
@message = message
|
48
|
+
@response = resp
|
49
|
+
end
|
50
|
+
|
51
|
+
# used to print the error nicely
|
52
|
+
def to_s
|
53
|
+
@message || super
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/riq/event.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'riq_obj'
|
2
|
+
using RIQExtensions
|
3
|
+
|
4
|
+
module RIQ
|
5
|
+
# Events represent interactions involving a Contact associated with a List Item.
|
6
|
+
class Event < RIQObject
|
7
|
+
attr_accessor :subject
|
8
|
+
attr_accessor :body
|
9
|
+
# attr_reader :participant_ids
|
10
|
+
|
11
|
+
# (see RIQObject#node)
|
12
|
+
def node
|
13
|
+
self.class.node
|
14
|
+
end
|
15
|
+
|
16
|
+
# (see RIQObject#node)
|
17
|
+
def self.node
|
18
|
+
"events"
|
19
|
+
end
|
20
|
+
|
21
|
+
# (see RIQObject#data)
|
22
|
+
def data
|
23
|
+
{
|
24
|
+
subject: @subject,
|
25
|
+
body: @body,
|
26
|
+
participant_ids: @participant_ids
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param type [Symbol] One of :email or :phone
|
31
|
+
# @param value [String] An email or phone number for the contact
|
32
|
+
def add_participant(type, value)
|
33
|
+
raise RIQError, 'Type must be :email or :phone' unless [:email, :phone].include?(type)
|
34
|
+
@participant_ids << {type: type, value: value}
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Array] Immutable copy of participant_ids
|
38
|
+
def participant_ids
|
39
|
+
@participant_ids.dup
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Hash] Success message, if successful.
|
43
|
+
def save
|
44
|
+
# there are no options to pass for event save
|
45
|
+
@client.put(node, payload, options: nil)
|
46
|
+
{status: 204, message: 'No Content'}
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def init(obj = nil)
|
51
|
+
unless obj.nil?
|
52
|
+
@subject = obj[:subject]
|
53
|
+
@body = obj[:body]
|
54
|
+
@participant_ids = []
|
55
|
+
obj[:participant_ids].each{|o| add_participant(o[:type], o[:value])}
|
56
|
+
else
|
57
|
+
@subject = nil
|
58
|
+
@body = nil
|
59
|
+
@participant_ids = []
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
# Convenience method to create new Events
|
67
|
+
# @param obj [Hash] Info to parse into event
|
68
|
+
# @return [Event]
|
69
|
+
def event(obj = nil)
|
70
|
+
Event.new(obj)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/riq/list.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative 'riq_obj'
|
2
|
+
|
3
|
+
module RIQ
|
4
|
+
# A List is an object that can be created and customized by a User to represent
|
5
|
+
# Accounts (companies) or Contacts (people) in a process (such as a sales pipeline).
|
6
|
+
class List < RIQObject
|
7
|
+
# can't create a list through API, so these don't need to write
|
8
|
+
attr_reader :title
|
9
|
+
attr_reader :type
|
10
|
+
attr_reader :list_items
|
11
|
+
# for consistency
|
12
|
+
alias_method :name, :title
|
13
|
+
|
14
|
+
# (see RIQObject#initialize)
|
15
|
+
def initialize(id = nil)
|
16
|
+
super
|
17
|
+
@list_items = ListItemManager.new(@id)
|
18
|
+
end
|
19
|
+
|
20
|
+
# (see RIQObject#node)
|
21
|
+
def node
|
22
|
+
self.class.node(@id)
|
23
|
+
end
|
24
|
+
|
25
|
+
# (see RIQObject.node)
|
26
|
+
def self.node(id = nil)
|
27
|
+
"lists/#{id}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# (see RIQObject#data)
|
31
|
+
def data
|
32
|
+
{
|
33
|
+
id: @id,
|
34
|
+
title: @title,
|
35
|
+
type: @type,
|
36
|
+
fields: @fields
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Overwriting parent because lists can't be saved through the API
|
41
|
+
def save
|
42
|
+
raise NotImplementedError, "Lists can't be edited through the API"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Gets field if it exists
|
46
|
+
# @param id [String, Integer] field ID
|
47
|
+
# @return [Hash, nil] info on the field specified
|
48
|
+
def fields(id = nil)
|
49
|
+
unless id.nil?
|
50
|
+
@fields.select{|f| f['id'] == id.to_s}.first
|
51
|
+
else
|
52
|
+
@fields
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Convenience method for fetching or creating a listitem from the given list
|
57
|
+
# @param oid [String, nil] ObjectId
|
58
|
+
def list_item(oid = nil)
|
59
|
+
RIQ::ListItem.new(oid, lid: @id)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def init(obj = nil)
|
65
|
+
unless obj.nil?
|
66
|
+
@id = obj[:id]
|
67
|
+
@title = obj[:title]
|
68
|
+
@type = obj[:listType]
|
69
|
+
@fields = obj[:fields]
|
70
|
+
else
|
71
|
+
@id = nil
|
72
|
+
@title = nil
|
73
|
+
@type = nil
|
74
|
+
@fields = nil
|
75
|
+
end
|
76
|
+
self
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class << self
|
81
|
+
# Convenience method to create new Lists
|
82
|
+
# @param id [String, nil] create a blank List object or
|
83
|
+
# fetch an existing one by id.
|
84
|
+
# @return [List]
|
85
|
+
def list(id = nil)
|
86
|
+
List.new(id)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require_relative 'riq_obj'
|
2
|
+
using RIQExtensions
|
3
|
+
|
4
|
+
module RIQ
|
5
|
+
# A List Item is a row in a List.
|
6
|
+
class ListItem < RIQObject
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :field_values
|
9
|
+
attr_accessor :account_id
|
10
|
+
attr_accessor :contact_ids
|
11
|
+
attr_accessor :list_id
|
12
|
+
|
13
|
+
attr_reader :modified_date
|
14
|
+
attr_reader :created_date
|
15
|
+
|
16
|
+
def initialize(id = nil, lid: nil)
|
17
|
+
if id.is_a? Hash
|
18
|
+
super(id)
|
19
|
+
elsif id.nil? && lid.nil?
|
20
|
+
super(nil)
|
21
|
+
elsif id.nil? && !lid.nil?
|
22
|
+
super(nil)
|
23
|
+
@list_id = lid
|
24
|
+
elsif id.nil? || lid.nil?
|
25
|
+
raise RIQError, 'ObjectID and List ID are required'
|
26
|
+
else
|
27
|
+
super("#{lid}/listitems/#{id}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# (see RIQObject#node)
|
32
|
+
def node
|
33
|
+
self.class.node(@list_id, @id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @note this is the only object for which you have to include two params
|
37
|
+
# @param lid [String] ListId that the lit item belongs to
|
38
|
+
# @param oid [String] ObjectId for the object
|
39
|
+
def self.node(lid = nil, oid = nil)
|
40
|
+
# weird workaround for fetching node on init
|
41
|
+
if lid.nil? && !oid.nil?
|
42
|
+
"lists/#{oid}"
|
43
|
+
else
|
44
|
+
"lists/#{lid || @list_id}/listitems/#{oid}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# (see RIQObject#data)
|
49
|
+
def data
|
50
|
+
{
|
51
|
+
name: @name,
|
52
|
+
account_id: @account_id,
|
53
|
+
contact_ids: @contact_ids.flatten,
|
54
|
+
id: @id,
|
55
|
+
list_id: @list_id,
|
56
|
+
field_values: @field_values,
|
57
|
+
modified_date: @modified_date
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
# (see RIQObject#payload)
|
62
|
+
def payload
|
63
|
+
pld = {}
|
64
|
+
data.each do |k, v|
|
65
|
+
if k == :field_values
|
66
|
+
pld['fieldValues'] = @field_values.to_raw
|
67
|
+
elsif k['_']
|
68
|
+
pld[k.to_cam] = v
|
69
|
+
else
|
70
|
+
pld[k] = v
|
71
|
+
end
|
72
|
+
end
|
73
|
+
pld.to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
# @overload field_value(key)
|
77
|
+
# @param key [String, Integer]
|
78
|
+
# @return [Array] Value of key
|
79
|
+
# @overload field_value(key, value)
|
80
|
+
# Sets key to value
|
81
|
+
# @param key [String, Integer] Key to set
|
82
|
+
# @param value [#to_s] Sets key to value
|
83
|
+
def field_value(key, value = nil)
|
84
|
+
# TODO: double check that this works with arrays of stuff
|
85
|
+
# or, have a format function that casts ints to string on save
|
86
|
+
if value.nil?
|
87
|
+
@field_values.fetch(key.to_sym, nil)
|
88
|
+
else
|
89
|
+
@field_values[key.to_sym] = value.to_s
|
90
|
+
{key.to_sym => value.to_s}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def init(obj = nil)
|
97
|
+
unless obj.nil?
|
98
|
+
@id = obj[:id]
|
99
|
+
@list_id = obj[:list_id]
|
100
|
+
@name = obj[:name]
|
101
|
+
@field_values = obj[:field_values] ? obj[:field_values].from_raw : {}
|
102
|
+
@account_id = obj[:account_id]
|
103
|
+
@contact_ids = obj[:contact_ids] || []
|
104
|
+
@modified_date = obj[:modified_date].cut_milis if obj[:modified_date]
|
105
|
+
@created_date = obj[:creaeted_date].cut_milis if obj[:creaeted_date]
|
106
|
+
else
|
107
|
+
@id = nil
|
108
|
+
@list_id = nil
|
109
|
+
@name = nil
|
110
|
+
@field_values = {}
|
111
|
+
@account_id = nil
|
112
|
+
@contact_ids = []
|
113
|
+
@modified_date = nil
|
114
|
+
@created_date = nil
|
115
|
+
end
|
116
|
+
self
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|