r_hapi 0.1.1 → 0.1.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.
- data/README.rdoc +29 -1
- data/VERSION +1 -1
- data/lib/r_hapi.rb +1 -0
- data/lib/r_hapi/connection.rb +56 -0
- data/lib/r_hapi/lead.rb +24 -17
- data/lib/r_hapi/r_hapi_exception.rb +12 -8
- data/r_hapi.gemspec +3 -2
- data/spec/lead_spec.rb +49 -9
- data/spec/spec_helper.rb +14 -9
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -10,6 +10,13 @@ RHapi is a Ruby wrapper for the HubSpot API (HAPI).
|
|
10
10
|
|
11
11
|
== Using RHapi
|
12
12
|
|
13
|
+
Intsall
|
14
|
+
If you use RVM.
|
15
|
+
gem install r_hapi
|
16
|
+
|
17
|
+
If not you may need to do this:
|
18
|
+
sudo gem install r_hapi
|
19
|
+
|
13
20
|
First configure RHapi to work with your Hubspot API Key.
|
14
21
|
|
15
22
|
RHapi.configure do |config|
|
@@ -28,12 +35,33 @@ Then to get a list of leads.
|
|
28
35
|
|
29
36
|
To find leads named Barny.
|
30
37
|
leads = RHapi::Lead.find("Barny")
|
38
|
+
|
39
|
+
You can also pass additional options to the find method.
|
40
|
+
options = {
|
41
|
+
:sort => "lastName", # Possible sort values include: firstName, lastName, email, address, phone, insertedAt, lastConvertedAt, lastModifiedAt, closedAt
|
42
|
+
:dir => "asc", # Use desc for descending.
|
43
|
+
:max => 25, # Maximum value is 100
|
44
|
+
:offset => 50, # Used in combination with max for paging results.
|
45
|
+
:startTime => 1298721462000, # Expressed as milliseconds since epoch time. Returned list will have only leads inserted after this time. Default is 0 and returns all leads up to max.
|
46
|
+
:stopTime => 1298721462000, # Expressed as milliseconds since epoch time.
|
47
|
+
:timePivot => "insertedAt", # The field the start and stop times should be applied to in the search. Can be: insertedAt, firstConvertedAt, lastConvertedAt, lastModifiedAt, closedAt.
|
48
|
+
:excludeConversionEvents => false, # Used to exclude all items in the leadConversionEvents collection from the API results.
|
49
|
+
:optout => false, # Set to true to include only leads that have unsubscribed from lead nurturing. The default value, false, includes all leads.
|
50
|
+
:eligibleForEmail => false, # Set to true to include only leads eligible for email marketing.
|
51
|
+
:bounced => false, # Set to true to include only leads that HubSpot has tried to email, and the email bounced. The default value, false, includes all leads.
|
52
|
+
:notImported => false # Set to true to include only web leads. The default value, false, includes both imported and web leads.
|
53
|
+
}
|
54
|
+
leads = RHapi::Lead.find("Barny", options)
|
31
55
|
|
32
56
|
To update a lead.
|
33
|
-
lead = leads.
|
57
|
+
lead = leads.first
|
34
58
|
lead.first_name = "Fred"
|
35
59
|
lead.last_name = "Flintsone"
|
36
60
|
lead.update
|
61
|
+
|
62
|
+
You can also pass a params hash to update a lead.
|
63
|
+
params = {:first_name => "Fred", :last_name => "Flintstone", :city => "Bedrock"}
|
64
|
+
lead.update(params)
|
37
65
|
|
38
66
|
To get a single lead with a guid. Assumes the guid has be saved from a previous search.
|
39
67
|
lead = RHapi::Lead.find_by_guid(lead.guid)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/r_hapi.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'curb'
|
2
|
+
require 'json'
|
3
|
+
module RHapi
|
4
|
+
module Connection
|
5
|
+
|
6
|
+
# Instance methods ---------------------------------------------------------------------------
|
7
|
+
|
8
|
+
def put(url, payload)
|
9
|
+
data = payload.to_json
|
10
|
+
response = Curl::Easy.http_put(url, data) do |curl|
|
11
|
+
curl.headers["Content-Type"] = "application/json"
|
12
|
+
curl.on_failure do |response, err|
|
13
|
+
RHapi::ConnectionError.raise_error("#{response.response_code}\n Error is: #{err.inspect}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
RHapi::ConnectionError.raise_error(response.header_str) unless response.header_str =~ /2\d\d/
|
17
|
+
end
|
18
|
+
|
19
|
+
# Class methods -----------------------------------------------------------------------------
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
|
23
|
+
def url_for(method, id=nil, options={})
|
24
|
+
url = "#{RHapi.options[:end_point]}/leads/#{RHapi.options[:version]}/#{method}"
|
25
|
+
url << "/#{id}" unless id.nil?
|
26
|
+
url << "?hapikey=#{RHapi.options[:api_key]}"
|
27
|
+
|
28
|
+
raise(RHapi::UriError, "Options must be a hash in order to build the url.") unless options.is_a?(Hash)
|
29
|
+
url << append_options(options) unless options.empty?
|
30
|
+
url
|
31
|
+
end
|
32
|
+
|
33
|
+
def append_options(options)
|
34
|
+
query_string = ""
|
35
|
+
options.each do |key, value|
|
36
|
+
query_string << "&#{key.to_s}=#{value}"
|
37
|
+
end
|
38
|
+
query_string
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(url)
|
42
|
+
response = Curl::Easy.perform(url) do |curl|
|
43
|
+
curl.on_failure do |response, err|
|
44
|
+
RHapi::ConnectionError.raise_error("#{response.response_code}\n Error is: #{err.inspect}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
RHapi::ConnectionError.raise_error( response.header_str) unless response.header_str =~ /2\d\d/
|
48
|
+
RHapi::ConnectionError.raise_error(response.body_str) if response.body_str =~ /Error/i
|
49
|
+
response
|
50
|
+
end
|
51
|
+
|
52
|
+
end # End class methods
|
53
|
+
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/r_hapi/lead.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'active_support'
|
3
3
|
require 'active_support/inflector/inflections'
|
4
|
+
require File.expand_path('../connection', __FILE__)
|
5
|
+
|
4
6
|
module RHapi
|
5
7
|
|
6
8
|
class Lead
|
9
|
+
include Connection
|
10
|
+
extend Connection::ClassMethods
|
7
11
|
|
8
12
|
attr_accessor :attributes, :changed_attributes
|
9
13
|
|
@@ -18,11 +22,11 @@ module RHapi
|
|
18
22
|
# An optional string value that is used to search several basic lead fields: first name, last name, email address,
|
19
23
|
# and company name. According to HubSpot docs, a more advanced search is coming in the future.
|
20
24
|
# The default value for is nil, meaning return all leads.
|
21
|
-
def self.find(search=nil)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
lead_data = JSON.parse(
|
25
|
+
def self.find(search=nil, options={})
|
26
|
+
options[:search] = search unless search.nil?
|
27
|
+
response = get(url_for("list", nil, options))
|
28
|
+
|
29
|
+
lead_data = JSON.parse(response.body_str)
|
26
30
|
leads = []
|
27
31
|
lead_data.each do |data|
|
28
32
|
lead = Lead.new(data)
|
@@ -33,25 +37,28 @@ module RHapi
|
|
33
37
|
|
34
38
|
# Finds specified lead by the guid.
|
35
39
|
def self.find_by_guid(guid)
|
36
|
-
|
37
|
-
|
38
|
-
RHapi::RHapiException.raise_error(c.body_str) if c.body_str =~ /Error/i
|
39
|
-
lead_data = JSON.parse(c.body_str)
|
40
|
+
response = get(url_for("lead", guid))
|
41
|
+
lead_data = JSON.parse(response.body_str)
|
40
42
|
Lead.new(lead_data)
|
41
43
|
end
|
42
44
|
|
43
45
|
# Instance methods -------------------------------------------------------
|
44
|
-
def update
|
45
|
-
|
46
|
-
|
47
|
-
c = Curl::Easy.http_put(url, data) do |curl|
|
48
|
-
curl.headers["Content-Type"] = "application/json"
|
49
|
-
curl.header_in_body = true
|
50
|
-
end
|
51
|
-
RHapi::RHapiException.raise_error(c.body_str) unless c.body_str =~ /200/i
|
46
|
+
def update(params={})
|
47
|
+
update_attributes(params) unless params.empty?
|
48
|
+
response = put(Lead.url_for("lead", self.guid), self.changed_attributes)
|
52
49
|
true
|
53
50
|
end
|
54
51
|
|
52
|
+
def update_attributes(params)
|
53
|
+
raise(RHapi::AttributeError, "The params must be a hash.") unless params.is_a?(Hash)
|
54
|
+
params.each do |key, value|
|
55
|
+
attribute = ActiveSupport::Inflector.camelize(key.to_s, false)
|
56
|
+
raise(RHapi::AttributeError, "No Hubspot attribute with the name #{attribute}.") unless self.attributes.include?(attribute)
|
57
|
+
self.changed_attributes[attribute] = value
|
58
|
+
self.attributes[attribute] = value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
55
62
|
|
56
63
|
|
57
64
|
# Work with data in the data hash
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module RHapi
|
2
|
-
class
|
2
|
+
class ConnectionError < StandardError
|
3
3
|
attr :error_string
|
4
4
|
|
5
5
|
def initialize(error_string)
|
@@ -8,21 +8,25 @@ module RHapi
|
|
8
8
|
|
9
9
|
def message
|
10
10
|
if @error_string =~ /401/
|
11
|
-
"HubSopt returned a 401 error
|
11
|
+
"HubSopt returned a 401 error: #{error_string}"
|
12
12
|
elsif @error_string =~ /404/
|
13
|
-
"HubSopt returned a 404 error
|
13
|
+
"HubSopt returned a 404 error: #{error_string}"
|
14
14
|
elsif @error_string =~ /500/
|
15
|
-
"HubSopt returned a 500 error
|
15
|
+
"HubSopt returned a 500 error: #{error_string}"
|
16
16
|
else
|
17
|
-
# else send back the whole message.
|
18
17
|
@error_string
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
|
-
def self.raise_error(
|
23
|
-
exception = RHapi::
|
21
|
+
def self.raise_error(response)
|
22
|
+
exception = RHapi::ConnectionError.new(response)
|
24
23
|
raise(exception, exception.message)
|
25
|
-
end
|
24
|
+
end
|
26
25
|
|
27
26
|
end
|
27
|
+
|
28
|
+
class UriError < TypeError; end
|
29
|
+
|
30
|
+
class AttributeError < TypeError; end
|
31
|
+
|
28
32
|
end
|
data/r_hapi.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{r_hapi}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tim Stephenson of RaddOnline"]
|
12
|
-
s.date = %q{2011-03-
|
12
|
+
s.date = %q{2011-03-22}
|
13
13
|
s.description = %q{Makes it easy to use the HubSpot API in a Ruby application.}
|
14
14
|
s.email = %q{tim@raddonline.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"lib/r_hapi.rb",
|
27
27
|
"lib/r_hapi/configuration.rb",
|
28
|
+
"lib/r_hapi/connection.rb",
|
28
29
|
"lib/r_hapi/lead.rb",
|
29
30
|
"lib/r_hapi/r_hapi_exception.rb",
|
30
31
|
"r_hapi.gemspec",
|
data/spec/lead_spec.rb
CHANGED
@@ -2,6 +2,34 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe "RHapi::Lead" do
|
4
4
|
|
5
|
+
context "connection" do
|
6
|
+
before do
|
7
|
+
RHapi.configure do |config|
|
8
|
+
config.api_key = test_config["api_key"]
|
9
|
+
config.hub_spot_site = "http://mysite.hubspot.com"
|
10
|
+
end
|
11
|
+
@url = "https://hubapi.com/leads/v1/list?hapikey=#{test_config["api_key"]}"
|
12
|
+
end
|
13
|
+
it "should generate a url with a search param" do
|
14
|
+
url = RHapi::Lead.url_for("list", nil, {:search => "test"})
|
15
|
+
url.should == @url << "&search=test"
|
16
|
+
end
|
17
|
+
it "should generate a url with multiple params" do
|
18
|
+
url = RHapi::Lead.url_for("list", nil, {:search => "test", :sort => "firstName", :dir => "asc", :max => 10})
|
19
|
+
url.include?("&sort=firstName").should == true
|
20
|
+
url.include?("&search=test").should == true
|
21
|
+
url.include?("&dir=asc").should == true
|
22
|
+
url.include?("&max=10").should == true
|
23
|
+
end
|
24
|
+
it "should generate a url with an id" do
|
25
|
+
url = RHapi::Lead.url_for("lead", "myid")
|
26
|
+
url.should == "https://hubapi.com/leads/v1/lead/myid?hapikey=#{test_config["api_key"]}"
|
27
|
+
end
|
28
|
+
it "should raise a url error if options is not a hash" do
|
29
|
+
lambda {RHapi::Lead.url_for("list", nil, nil)}.should raise_error(RHapi::UriError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
5
33
|
context "when searching for leads" do
|
6
34
|
before do
|
7
35
|
RHapi.configure do |config|
|
@@ -37,8 +65,7 @@ describe "RHapi::Lead" do
|
|
37
65
|
lead.analytics_details.length.should == 12
|
38
66
|
lead.analytics_details["allViewsImported"].should == true
|
39
67
|
end
|
40
|
-
|
41
|
-
|
68
|
+
|
42
69
|
end
|
43
70
|
|
44
71
|
context "updating a lead" do
|
@@ -64,18 +91,32 @@ describe "RHapi::Lead" do
|
|
64
91
|
stub_lead_update
|
65
92
|
leads = RHapi::Lead.find
|
66
93
|
lead = leads.first
|
67
|
-
lead.first_name = "
|
68
|
-
lead.last_name = "
|
94
|
+
lead.first_name = "Adam"
|
95
|
+
lead.last_name = "Enbar"
|
69
96
|
lead.update.should == true
|
70
97
|
end
|
71
98
|
|
99
|
+
it "should have a list of changed attributes when updating with a params hash" do
|
100
|
+
stub_lead_update
|
101
|
+
leads = RHapi::Lead.find
|
102
|
+
lead = leads.first
|
103
|
+
lead.update({:first_name => "Wilma", :last_name => "Flintstone", :city => "Bedrock", :state => "CA"}).should == true
|
104
|
+
lead.changed_attributes.length.should == 4
|
105
|
+
lead.changed_attributes["firstName"].should == "Wilma"
|
106
|
+
lead.changed_attributes["firstName"].should == "Wilma"
|
107
|
+
lead.changed_attributes["city"].should == "Bedrock"
|
108
|
+
lead.changed_attributes["state"].should == "CA"
|
109
|
+
end
|
110
|
+
|
72
111
|
it "should raise an error if 200 is not returned" do
|
73
|
-
stub_lead_update_error
|
74
112
|
leads = RHapi::Lead.find
|
75
113
|
lead = leads.first
|
76
114
|
lead.first_name = "Barny"
|
77
115
|
lead.last_name = "Rubble"
|
78
|
-
|
116
|
+
lead.guid = "wrong"
|
117
|
+
stub_lead_update_error
|
118
|
+
|
119
|
+
lambda {lead.update}.should raise_error(RHapi::ConnectionError)
|
79
120
|
end
|
80
121
|
|
81
122
|
end
|
@@ -97,9 +138,8 @@ describe "RHapi::Lead" do
|
|
97
138
|
end
|
98
139
|
|
99
140
|
it "should raise an error if an error string is returned" do
|
100
|
-
leads = RHapi::Lead.find
|
101
141
|
stub_leads_error
|
102
|
-
lambda {RHapi::Lead.find_by_guid(
|
142
|
+
lambda {RHapi::Lead.find_by_guid("badguid")}.should raise_error(RHapi::ConnectionError)
|
103
143
|
end
|
104
144
|
end
|
105
145
|
|
@@ -114,7 +154,7 @@ describe "RHapi::Lead" do
|
|
114
154
|
|
115
155
|
it "should raise an exception" do
|
116
156
|
stub_leads_error
|
117
|
-
lambda {RHapi::Lead.find}.should raise_error(RHapi::
|
157
|
+
lambda {RHapi::Lead.find}.should raise_error(RHapi::ConnectionError)
|
118
158
|
end
|
119
159
|
end
|
120
160
|
|
data/spec/spec_helper.rb
CHANGED
@@ -29,31 +29,36 @@ def test_error
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def stub_leads_search
|
32
|
-
@
|
33
|
-
@
|
34
|
-
|
32
|
+
@response = mock("response_data")
|
33
|
+
@response.stub!(:body_str).and_return(test_leads)
|
34
|
+
@response.stub!(:header_str).and_return("200 OK")
|
35
|
+
Curl::Easy.stub!(:perform).and_return(@response)
|
35
36
|
end
|
36
37
|
|
37
38
|
def stub_leads_find_by_guid
|
38
|
-
@
|
39
|
-
@
|
40
|
-
|
39
|
+
@response = mock("response_data")
|
40
|
+
@response.stub!(:body_str).and_return(test_lead)
|
41
|
+
@response.stub!(:header_str).and_return("200 OK")
|
42
|
+
Curl::Easy.stub!(:perform).and_return(@response)
|
41
43
|
end
|
42
44
|
|
43
45
|
def stub_leads_error
|
44
|
-
@
|
45
|
-
@
|
46
|
-
|
46
|
+
@response = mock("response_data")
|
47
|
+
@response.stub!(:body_str).and_return(test_error)
|
48
|
+
@response.stub!(:header_str).and_return("404")
|
49
|
+
Curl::Easy.stub!(:perform).and_return(@response)
|
47
50
|
end
|
48
51
|
|
49
52
|
def stub_lead_update
|
50
53
|
@response_mock = mock("data")
|
51
54
|
@response_mock.stub!(:body_str).and_return("200 OK")
|
55
|
+
@response_mock.stub!(:header_str).and_return("200 OK")
|
52
56
|
Curl::Easy.stub!(:http_put).and_return(@response_mock)
|
53
57
|
end
|
54
58
|
|
55
59
|
def stub_lead_update_error
|
56
60
|
@response_mock = mock("data")
|
61
|
+
@response_mock.stub!(:header_str).and_return("500")
|
57
62
|
@response_mock.stub!(:body_str).and_return("Error: 500 internal server error.")
|
58
63
|
Curl::Easy.stub!(:http_put).and_return(@response_mock)
|
59
64
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: r_hapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tim Stephenson of RaddOnline
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-22 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- VERSION
|
191
191
|
- lib/r_hapi.rb
|
192
192
|
- lib/r_hapi/configuration.rb
|
193
|
+
- lib/r_hapi/connection.rb
|
193
194
|
- lib/r_hapi/lead.rb
|
194
195
|
- lib/r_hapi/r_hapi_exception.rb
|
195
196
|
- r_hapi.gemspec
|