r_hapi 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|