hubspot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +149 -0
  3. data/Rakefile +38 -0
  4. data/app/helpers/hubspot_helper.rb +17 -0
  5. data/app/models/hubspot/base.rb +40 -0
  6. data/app/models/hubspot/blog.rb +35 -0
  7. data/app/models/hubspot/blogs/blog_association.rb +35 -0
  8. data/app/models/hubspot/blogs/comment.rb +5 -0
  9. data/app/models/hubspot/blogs/post.rb +12 -0
  10. data/app/models/hubspot/blogs/posts/comment.rb +23 -0
  11. data/app/models/hubspot/connection.rb +35 -0
  12. data/app/models/hubspot/event.rb +39 -0
  13. data/app/models/hubspot/keyword.rb +49 -0
  14. data/app/models/hubspot/lead.rb +26 -0
  15. data/app/models/hubspot/performable/event.rb +67 -0
  16. data/lib/hubspot.rb +8 -0
  17. data/lib/hubspot/action_controller_extensions.rb +15 -0
  18. data/lib/hubspot/engine.rb +30 -0
  19. data/lib/hubspot/version.rb +3 -0
  20. data/lib/tasks/hubspot_tasks.rake +4 -0
  21. data/test/dummy/README.rdoc +261 -0
  22. data/test/dummy/Rakefile +7 -0
  23. data/test/dummy/app/assets/javascripts/application.js +15 -0
  24. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  25. data/test/dummy/app/controllers/application_controller.rb +3 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  28. data/test/dummy/config.ru +4 -0
  29. data/test/dummy/config/application.rb +56 -0
  30. data/test/dummy/config/boot.rb +10 -0
  31. data/test/dummy/config/database.yml +25 -0
  32. data/test/dummy/config/environment.rb +5 -0
  33. data/test/dummy/config/environments/development.rb +37 -0
  34. data/test/dummy/config/environments/production.rb +67 -0
  35. data/test/dummy/config/environments/test.rb +37 -0
  36. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  37. data/test/dummy/config/initializers/inflections.rb +15 -0
  38. data/test/dummy/config/initializers/mime_types.rb +5 -0
  39. data/test/dummy/config/initializers/secret_token.rb +7 -0
  40. data/test/dummy/config/initializers/session_store.rb +8 -0
  41. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  42. data/test/dummy/config/locales/en.yml +5 -0
  43. data/test/dummy/config/routes.rb +58 -0
  44. data/test/dummy/db/test.sqlite3 +0 -0
  45. data/test/dummy/log/test.log +2056 -0
  46. data/test/dummy/public/404.html +26 -0
  47. data/test/dummy/public/422.html +26 -0
  48. data/test/dummy/public/500.html +25 -0
  49. data/test/dummy/public/favicon.ico +0 -0
  50. data/test/dummy/script/rails +6 -0
  51. data/test/fixtures/vcr_cassettes/blog-comments.yml +74 -0
  52. data/test/fixtures/vcr_cassettes/blog-find.yml +36 -0
  53. data/test/fixtures/vcr_cassettes/blog-posts.yml +75 -0
  54. data/test/fixtures/vcr_cassettes/blogs-list.yml +39 -0
  55. data/test/fixtures/vcr_cassettes/event-create.yml +36 -0
  56. data/test/fixtures/vcr_cassettes/event-record.yml +47 -0
  57. data/test/fixtures/vcr_cassettes/events-list.yml +41 -0
  58. data/test/fixtures/vcr_cassettes/keyword-create.yml +36 -0
  59. data/test/fixtures/vcr_cassettes/keywords-list.yml +385 -0
  60. data/test/fixtures/vcr_cassettes/lead-find.yml +103 -0
  61. data/test/fixtures/vcr_cassettes/lead-update.yml +239 -0
  62. data/test/fixtures/vcr_cassettes/leads-list.yml +190 -0
  63. data/test/fixtures/vcr_cassettes/post-comments.yml +72 -0
  64. data/test/fixtures/vcr_cassettes/post-find.yml +39 -0
  65. data/test/hubspot_test.rb +5 -0
  66. data/test/test_helper.rb +22 -0
  67. data/test/unit/blog_test.rb +37 -0
  68. data/test/unit/event_test.rb +21 -0
  69. data/test/unit/keyword_test.rb +22 -0
  70. data/test/unit/lead_test.rb +31 -0
  71. data/test/unit/performable_event_test.rb +22 -0
  72. data/test/unit/post_test.rb +20 -0
  73. metadata +207 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Reinier de Lange
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,149 @@
1
+ = Hubspot
2
+
3
+ This gem is a Rails Engine for communicating with several Hubspot API's. Furthermore, it provides some helpers
4
+ to easily integrate Hubspot in your website. This gem only uses standard ActiveResource and Net/HTTP and has been
5
+ tested with unit tests and VCR for replaying HTTP requests.
6
+
7
+ == Requirements
8
+
9
+ Rails 3
10
+
11
+ == Installation
12
+
13
+ Add hubspot to your Gemfile:
14
+
15
+ gem 'hubspot'
16
+
17
+ == Configuration
18
+
19
+ This gem is a Rails Engine. The gem can be configured by changing the default engine configuration. The following settings
20
+ can be added to your application.rb or an initializer:
21
+
22
+ * Hubspot.config.hubspot_site = 'demo.app11.hubspot.com'
23
+ The domain of your Hubspot site, which is used in the javascript tracker code
24
+
25
+ * Hubspot.config.hubspot_access_token = 'demooooo-oooo-oooo-oooo-oooooooooooo'
26
+ The access token for authenticating to several Hubspot services
27
+
28
+ * Hubspot.config.hubspot_key = 'demo'
29
+ Your API key
30
+
31
+ * Hubspot.config.hubspot_portal_id = '62515'
32
+ Your Portal ID
33
+
34
+ * Hubspot.config.debug_http_output = false
35
+ Enables/disables logging of HTTP requests and response. False disables debugging, setting it to STDOUT enables logging to STDOUT. Of course you can specify any IO object you want.
36
+
37
+ == Usage
38
+
39
+ Currently, the gem supports the following Hubspot API's:
40
+
41
+ * Leads
42
+
43
+ See: http://developers.hubspot.com/docs/endpoints#leads-api
44
+
45
+ ** Finds
46
+
47
+ Hubspot::Lead.find :all, :params => { :search => 'test' }
48
+ Hubspot::Lead.find <GUID>
49
+
50
+ ** Updates
51
+
52
+ lead.firstName = 'Reinier'; lead.save!
53
+ lead.update_attributes(:firstName => 'Reinier')
54
+
55
+ * Blogs (including posts and comments)
56
+
57
+ See: http://developers.hubspot.com/docs/endpoints#blog-api
58
+
59
+ ** Finds
60
+ Hubspot::Blog.find :all, :params => { :max => 10 }
61
+ Hubspot::Blog.find <GUID>
62
+
63
+ ** Posts
64
+ Hubspot::Blog.find('guid').posts
65
+
66
+ *** Post comments
67
+ Hubspot::Blogs::Post.find("6ca6fdc5-a81f-44db-a63b-f56ab2636c69", :params => { :blog_guid => "0d61e4ca-e395-4c1c-8766-afaa48bf68db" }).comments
68
+
69
+ ** Comments
70
+ Hubspot::Blog.find('guid').comments
71
+
72
+ * Keywords
73
+
74
+ See: http://developers.hubspot.com/docs/endpoints#keywords-api
75
+
76
+ ** Finds
77
+
78
+ Hubspot::Keyword.find(:all, :params => { :max => 5 })
79
+ Hubspot::Keyword.find('guid')
80
+
81
+ ** Creates
82
+
83
+ Hubspot::Keyword.create!({ :keyword => { :keyword => 'key' }})
84
+ Hubspot::Keyword.create({ :keyword => { :keyword => 'key' }})
85
+
86
+ * Events
87
+
88
+ See: http://developers.hubspot.com/docs/endpoints#events-api
89
+
90
+ ** Finds
91
+
92
+ Hubspot::Event.find(:all, :params => { :max => 5 })
93
+
94
+ ** Creates
95
+
96
+ Hubspot::Event.create!(:eventType => 'new event', :description => 'test')
97
+ Hubspot::Event.create(:eventType => 'new event', :description => 'test')
98
+
99
+ * Performable events
100
+
101
+ See: http://performabledoc.hubspot.com/display/DOC/HTTP+API
102
+
103
+ ** Records
104
+
105
+ event = Hubspot::Performable::Event.new('event-12345', Date.civil(2012), nil, 'http://example.com')
106
+ event.custom_parameters = { :email => 'test@example.com' }
107
+ event.save!
108
+
109
+ Please take a look at the unit tests for examples!
110
+
111
+ == Action controller extensions
112
+
113
+ For now, there is only a convenience method for getting the current user token:
114
+
115
+ hubspot_user_token # Retrieves the user token from the Hubspot 'hubspotutk' cookie (if any)
116
+
117
+ == HubspotHelper
118
+
119
+ The HubspotHelper can be used to insert the Hubspot javascript tracker code to your website. First include the helper:
120
+
121
+ class ApplicationController < ActionController::Base
122
+ helper HubspotHelper
123
+ end
124
+
125
+ Then, you can add the javascript tracker code easily by calling the helper:
126
+
127
+ <body>
128
+ ...
129
+ <%= hubspot_javascript_tracker %>
130
+ </body>
131
+
132
+ == Acknowledgements
133
+
134
+ * Thanks go to Josh Lane from which I took some of the code of his Hubspot API implementation (https://github.com/lanej/hubspot-api)
135
+
136
+ == Note on Patches/Pull Requests
137
+
138
+ * Fork the project.
139
+ * Make your feature addition or bug fix.
140
+ * Add tests for it. This is important so I don't break it in a
141
+ future version unintentionally.
142
+ * Commit, do not mess with rakefile, version, or history.
143
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
144
+ * Send me a pull request. Bonus points for topic branches.
145
+
146
+ == Copyright
147
+
148
+ Copyright (c) 2012 Reinier de Lange. See LICENSE for details.
149
+
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Hubspot'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,17 @@
1
+ module HubspotHelper
2
+
3
+ # Should be included at the bottom of any HTML page (before </body>) you want to track
4
+ def hubspot_javascript_tracker
5
+ raw <<-EOS
6
+ <!-- Start of HubSpot Logging Code -->
7
+ <script type="text/javascript" language="javascript">
8
+ var hs_portalid=#{Hubspot.config.hubspot_portal_id};
9
+ var hs_salog_version = "2.00";
10
+ var hs_ppa = "#{Hubspot.config.hubspot_site}";
11
+ document.write(unescape("%3Cscript src='" + document.location.protocol + "//" + hs_ppa + "/salog.js.aspx' type='text/javascript'%3E%3C/script%3E"));
12
+ </script>
13
+ <!-- End of HubSpot Logging Code -->
14
+ EOS
15
+ end
16
+
17
+ end
@@ -0,0 +1,40 @@
1
+ require "active_resource"
2
+
3
+ # Hubspot::Base initializes ActiveResource to use JSON and to use our own Connection class that adds authentication
4
+ # information to each request. Moreover, as Hubspot's API paths are very inconsistent, it provides the most common
5
+ # paths to object collections and members. This can be overridden if necessary
6
+ module Hubspot
7
+
8
+ class Base < ActiveResource::Base
9
+ self.format = ActiveResource::Formats::JsonFormat
10
+
11
+ # Only serialize the attributes listed in the schema. Leads can contain much more information than can be passed
12
+ # back to Hubspot, therefore we need to ensure they are not serialized on save.
13
+ def to_json(options={})
14
+ super(options.reverse_merge(:root => nil, :only => schema.keys))
15
+ end
16
+
17
+ class << self
18
+
19
+ # Use our own connection class
20
+ def connection(refresh = false)
21
+ @connection = Hubspot::Connection.new(site, format) if @connection.nil? || refresh
22
+ return @connection
23
+ end
24
+
25
+ # ==== Set paths ====
26
+
27
+ def element_path(id, prefix_options = {}, query_options = nil)
28
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
29
+ "#{prefix(prefix_options)}#{collection_name.singularize}/#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
30
+ end
31
+
32
+ def collection_path(prefix_options = {}, query_options = nil)
33
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
34
+ "#{prefix(prefix_options)}list.#{format.extension}#{query_string(query_options)}"
35
+ end
36
+
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,35 @@
1
+ module Hubspot
2
+
3
+ # Finds blogs
4
+ #
5
+ # Finds:
6
+ # Hubspot::Blog.find :all, :params => { :max => 10 }
7
+ # Hubspot::Blog.find <GUID>
8
+ class Blog < Hubspot::Base
9
+ self.site = 'https://api.hubapi.com/blog/v1'
10
+
11
+ schema do
12
+ string 'guid', 'blogTitle', 'feedUrl', 'jsonUrl', 'webUrl'
13
+ end
14
+
15
+ alias_attribute :id, :guid
16
+
17
+ # Convenience methods for retrieving a blog's posts and comments
18
+
19
+ def comments(params = {})
20
+ Hubspot::Blogs::Comment.find :all, :params => params.merge(:blog_guid => guid)
21
+ end
22
+
23
+ def posts(params = {})
24
+ Hubspot::Blogs::Post.find :all, :params => params.merge(:blog_guid => guid)
25
+ end
26
+
27
+ # Explicitly set element path
28
+ def self.element_path(id, prefix_options = {}, query_options = nil)
29
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
30
+ "#{prefix(prefix_options)}#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,35 @@
1
+ module Hubspot
2
+ module Blogs
3
+
4
+ # Define an assocation base class from which blog child associations should inherit
5
+ class BlogAssociation < Hubspot::Base
6
+ self.site = Hubspot::Blog.site
7
+
8
+ alias_attribute :id, :guid
9
+
10
+ class << self
11
+ def element_path(id, prefix_options = {}, query_options = nil)
12
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
13
+ "#{prefix(prefix_options)}#{collection_name}/#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
14
+ end
15
+
16
+ def collection_path(prefix_options = {}, query_options = nil)
17
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
18
+ raise(ActiveResource::MissingPrefixParam, ":blog_guid prefix_option is missing") unless prefix_options[:blog_guid] && defined?(ActiveResource::MissingPrefixParam)
19
+ "#{prefix(prefix_options)}#{prefix_options[:blog_guid].to_s}/#{collection_name}.#{format.extension}#{query_string(query_options)}"
20
+ end
21
+
22
+ private
23
+
24
+ def prefix_parameters
25
+ @prefix_parameters ||= begin
26
+ params = super
27
+ params << :blog_guid
28
+ params
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ module Hubspot
2
+ module Blogs
3
+ class Comment < Hubspot::Blogs::BlogAssociation; end
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module Hubspot
2
+ module Blogs
3
+ class Post < Hubspot::Blogs::BlogAssociation
4
+
5
+ # Convenience method for retrieving a post's comments
6
+ def comments(params = {})
7
+ Hubspot::Blogs::Posts::Comment.find :all, :params => params.merge(:post_guid => guid)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ module Hubspot
2
+ module Blogs
3
+ module Posts
4
+
5
+ # This type of Comment will be instantiated when finding comments that belong to Posts
6
+ class Comment < Hubspot::Base
7
+ self.site = 'https://api.hubapi.com/blog/v1/posts/:post_guid'
8
+
9
+ alias_attribute :id, :guid
10
+
11
+ class << self
12
+
13
+ def collection_path(prefix_options = {}, query_options = nil)
14
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
15
+ "#{prefix(prefix_options)}comments.#{format.extension}#{query_string(query_options)}"
16
+ end
17
+
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ module Hubspot
2
+
3
+ class Connection < ActiveResource::Connection
4
+
5
+ # Set default parameters to send along with each request
6
+ def self.default_parameters
7
+ @default_parameters ||= { 'access_token' => Hubspot.config.hubspot_access_token, 'portalId' => Hubspot.config.hubspot_portal_id }
8
+ end
9
+
10
+ # Override to support debug output
11
+ def configure_http(http)
12
+ http.set_debug_output(Hubspot.config.debug_http_output) if Hubspot.config.debug_http_output
13
+ super
14
+ end
15
+
16
+ private
17
+
18
+ # Makes a request to the remote service and appends the default parameters
19
+ def request(method, path, *arguments)
20
+ uri = URI.parse(path)
21
+
22
+ Hubspot::Connection.default_parameters.to_param.tap do |default_parameters|
23
+ if uri.query.present?
24
+ uri.query += '&' + default_parameters
25
+ else
26
+ uri.query = default_parameters
27
+ end
28
+ end
29
+
30
+ super(method, uri.to_s, *arguments)
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,39 @@
1
+ module Hubspot
2
+
3
+ # Finds and updates events
4
+ #
5
+ # Finds:
6
+ # Hubspot::Event.find :all, :params => { :max => 5 }
7
+ #
8
+ # Creates:
9
+ # Hubspot::Event.create(:eventType => 'new event', :description => 'test', :url => 'http://dev.hubspot.com', :createDate => '1323272544000' )
10
+ class Event < Hubspot::Base
11
+ self.site = 'https://api.hubapi.com/events/v1'
12
+
13
+ schema do
14
+ string 'description', 'eventType', 'url', 'createDate'
15
+ end
16
+
17
+ class << self
18
+ def create attributes
19
+ create!(attributes) rescue false
20
+ end
21
+
22
+ def create! attributes
23
+ return Hubspot::Event.post('events', attributes).code.to_i
24
+ end
25
+
26
+ def custom_method_collection_url(method_name, options = {})
27
+ prefix_options, query_options = split_options(options)
28
+ "#{prefix(prefix_options)}#{method_name}#{query_string(query_options)}"
29
+ end
30
+
31
+ def collection_path(prefix_options = {}, query_options = nil)
32
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
33
+ "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end