hashblue-api 0.0.8
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 +21 -0
- data/Rakefile +98 -0
- data/hashblue-api.gemspec +58 -0
- data/lib/dependency/mime_type.rb +231 -0
- data/lib/dependency/mime_types.rb +23 -0
- data/lib/hashblue/api.rb +89 -0
- data/lib/hashblue/api/contact.rb +26 -0
- data/lib/hashblue/api/error.rb +39 -0
- data/lib/hashblue/api/message.rb +37 -0
- data/lib/hashblue/api/model.rb +55 -0
- data/lib/hashblue/api/request.rb +36 -0
- data/lib/hashblue/api/subscriber.rb +65 -0
- data/lib/hashblue/api/test_helper.rb +87 -0
- data/test/helpers/test_helper_test.rb +115 -0
- data/test/test_helper.rb +32 -0
- data/test/unit/api_test.rb +17 -0
- data/test/unit/contact_test.rb +27 -0
- data/test/unit/message_api_test.rb +135 -0
- data/test/unit/message_test.rb +42 -0
- data/test/unit/model_test.rb +27 -0
- data/test/unit/subscriber_test.rb +42 -0
- metadata +110 -0
data/README
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= It's the Hashblue API gem
|
2
|
+
|
3
|
+
For usage, look at Hashblue::API (in lib/firehose/api.rb)
|
4
|
+
|
5
|
+
|
6
|
+
= Short usage example
|
7
|
+
|
8
|
+
require 'active_support/all' # unless you have already loaded it
|
9
|
+
require 'hashblue/api'
|
10
|
+
|
11
|
+
Hashblue::API.base_uri "https://api.hashblue.apigee.com"
|
12
|
+
Hashblue::API.basic_auth "dave@example.com", "yourapikey"
|
13
|
+
|
14
|
+
subscriber = Hashblue::API::Subscriber.find("yourapikey")
|
15
|
+
|
16
|
+
subscriber.messages
|
17
|
+
|
18
|
+
|
19
|
+
= Testing against the Hashblue API
|
20
|
+
|
21
|
+
To learn about stubbing out the Hashblue API, see Hashblue::API::TestHelper
|
data/Rakefile
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/gempackagetask"
|
3
|
+
require "rake/rdoctask"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
# This builds the actual gem. For details of what all these options
|
9
|
+
# mean, and other ones you can add, check the documentation here:
|
10
|
+
#
|
11
|
+
# http://rubygems.org/read/chapter/20
|
12
|
+
#
|
13
|
+
path = File.expand_path("..", __FILE__)
|
14
|
+
|
15
|
+
spec = Dir.chdir(path) do
|
16
|
+
Gem::Specification.new do |s|
|
17
|
+
|
18
|
+
# Change these as appropriate
|
19
|
+
s.name = "hashblue-api"
|
20
|
+
s.version = "0.0.8"
|
21
|
+
s.summary = "It's the Hashblue API, stupid!"
|
22
|
+
s.author = "FreeRange"
|
23
|
+
s.email = "lets@gofreerange.com"
|
24
|
+
s.homepage = "http://gofreerange.com"
|
25
|
+
|
26
|
+
s.has_rdoc = true
|
27
|
+
s.extra_rdoc_files = %w(README)
|
28
|
+
s.rdoc_options = %w(--main README)
|
29
|
+
|
30
|
+
# Add any extra files to include in the gem
|
31
|
+
s.files = `cd #{path} && git ls-files`.split("\n").sort
|
32
|
+
|
33
|
+
# You need to put your code in a directory which can then be added to
|
34
|
+
# the $LOAD_PATH by rubygems. Typically this is lib, but you don't seem
|
35
|
+
# to have that directory. You'll need to set the line below to whatever
|
36
|
+
# directory your code is in. Rubygems is going to assume lib if you leave
|
37
|
+
# this blank.
|
38
|
+
#
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
|
41
|
+
# If you want to depend on other gems, add them here, along with any
|
42
|
+
# relevant versions
|
43
|
+
s.add_dependency 'httparty', '0.5.2'
|
44
|
+
s.add_dependency 'activesupport', '>= 2.3.5'
|
45
|
+
|
46
|
+
# If your tests use any gems, include them here
|
47
|
+
# s.add_development_dependency("mocha") # for example
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Stolen from jeweler
|
52
|
+
def prettyify_array(gemspec_ruby, array_name)
|
53
|
+
gemspec_ruby.gsub(/s\.#{array_name.to_s} = \[.+?\]/) do |match|
|
54
|
+
leadin, files = match[0..-2].split("[")
|
55
|
+
leadin + "[\n #{files.split(",").join(",\n ")}\n ]"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
Rake::TestTask.new do |t|
|
60
|
+
t.libs << "test"
|
61
|
+
t.test_files = FileList["#{path}/test/**/*test.rb"]
|
62
|
+
t.verbose = true
|
63
|
+
end
|
64
|
+
|
65
|
+
# This task actually builds the gem. We also regenerate a static
|
66
|
+
# .gemspec file, which is useful if something (i.e. GitHub) will
|
67
|
+
# be automatically building a gem for this project. If you're not
|
68
|
+
# using GitHub, edit as appropriate.
|
69
|
+
#
|
70
|
+
# To publish your gem online, install the 'gemcutter' gem; Read more
|
71
|
+
# about that here: http://gemcutter.org/pages/gem_docs
|
72
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
73
|
+
pkg.gem_spec = spec
|
74
|
+
end
|
75
|
+
|
76
|
+
task :gemspec do
|
77
|
+
output = spec.to_ruby
|
78
|
+
output = prettyify_array(output, :files)
|
79
|
+
output = prettyify_array(output, :test_files)
|
80
|
+
output = prettyify_array(output, :extra_rdoc_files)
|
81
|
+
|
82
|
+
file = File.expand_path("../#{spec.name}.gemspec", __FILE__)
|
83
|
+
File.open(file, "w") {|f| f << output }
|
84
|
+
end
|
85
|
+
|
86
|
+
task :package => :gemspec
|
87
|
+
|
88
|
+
# Generate documentation
|
89
|
+
Rake::RDocTask.new do |rd|
|
90
|
+
rd.main = "README"
|
91
|
+
rd.rdoc_files.include("README", "lib/**/*.rb")
|
92
|
+
rd.rdoc_dir = "rdoc"
|
93
|
+
end
|
94
|
+
|
95
|
+
desc 'Clear out RDoc and generated packages'
|
96
|
+
task :clean => [:clobber_rdoc, :clobber_package] do
|
97
|
+
rm "#{spec.name}.gemspec"
|
98
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{hashblue-api}
|
5
|
+
s.version = "0.0.8"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["FreeRange"]
|
9
|
+
s.date = %q{2010-05-06}
|
10
|
+
s.email = %q{lets@gofreerange.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"README"
|
13
|
+
]
|
14
|
+
s.files = [
|
15
|
+
"README",
|
16
|
+
"Rakefile",
|
17
|
+
"hashblue-api.gemspec",
|
18
|
+
"lib/dependency/mime_type.rb",
|
19
|
+
"lib/dependency/mime_types.rb",
|
20
|
+
"lib/hashblue/api.rb",
|
21
|
+
"lib/hashblue/api/contact.rb",
|
22
|
+
"lib/hashblue/api/error.rb",
|
23
|
+
"lib/hashblue/api/message.rb",
|
24
|
+
"lib/hashblue/api/model.rb",
|
25
|
+
"lib/hashblue/api/request.rb",
|
26
|
+
"lib/hashblue/api/subscriber.rb",
|
27
|
+
"lib/hashblue/api/test_helper.rb",
|
28
|
+
"test/helpers/test_helper_test.rb",
|
29
|
+
"test/test_helper.rb",
|
30
|
+
"test/unit/api_test.rb",
|
31
|
+
"test/unit/contact_test.rb",
|
32
|
+
"test/unit/message_api_test.rb",
|
33
|
+
"test/unit/message_test.rb",
|
34
|
+
"test/unit/model_test.rb",
|
35
|
+
"test/unit/subscriber_test.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://gofreerange.com}
|
38
|
+
s.rdoc_options = ["--main", "README"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.6}
|
41
|
+
s.summary = %q{It's the Hashblue API, stupid!}
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_runtime_dependency(%q<httparty>, ["= 0.5.2"])
|
49
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<httparty>, ["= 0.5.2"])
|
52
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<httparty>, ["= 0.5.2"])
|
56
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
+
|
4
|
+
module Mime
|
5
|
+
class Mimes < Array
|
6
|
+
def symbols
|
7
|
+
@symbols ||= map {|m| m.to_sym }
|
8
|
+
end
|
9
|
+
|
10
|
+
%w(<< concat shift unshift push pop []= clear compact! collect!
|
11
|
+
delete delete_at delete_if flatten! map! insert reject! reverse!
|
12
|
+
replace slice! sort! uniq!).each do |method|
|
13
|
+
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
14
|
+
def #{method}(*)
|
15
|
+
@symbols = nil
|
16
|
+
super
|
17
|
+
end
|
18
|
+
CODE
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
SET = Mimes.new
|
23
|
+
EXTENSION_LOOKUP = {}
|
24
|
+
LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
|
25
|
+
|
26
|
+
def self.[](type)
|
27
|
+
return type if type.is_a?(Type)
|
28
|
+
Type.lookup_by_extension(type.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Encapsulates the notion of a mime type. Can be used at render time, for example, with:
|
32
|
+
#
|
33
|
+
# class PostsController < ActionController::Base
|
34
|
+
# def show
|
35
|
+
# @post = Post.find(params[:id])
|
36
|
+
#
|
37
|
+
# respond_to do |format|
|
38
|
+
# format.html
|
39
|
+
# format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] }
|
40
|
+
# format.xml { render :xml => @people.to_xml }
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
class Type
|
45
|
+
@@html_types = Set.new [:html, :all]
|
46
|
+
cattr_reader :html_types
|
47
|
+
|
48
|
+
# These are the content types which browsers can generate without using ajax, flash, etc
|
49
|
+
# i.e. following a link, getting an image or posting a form. CSRF protection
|
50
|
+
# only needs to protect against these types.
|
51
|
+
@@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text]
|
52
|
+
cattr_reader :browser_generated_types
|
53
|
+
attr_reader :symbol
|
54
|
+
|
55
|
+
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
|
56
|
+
def self.unverifiable_types
|
57
|
+
ActiveSupport::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller)
|
58
|
+
@@unverifiable_types
|
59
|
+
end
|
60
|
+
|
61
|
+
# A simple helper class used in parsing the accept header
|
62
|
+
class AcceptItem #:nodoc:
|
63
|
+
attr_accessor :order, :name, :q
|
64
|
+
|
65
|
+
def initialize(order, name, q=nil)
|
66
|
+
@order = order
|
67
|
+
@name = name.strip
|
68
|
+
q ||= 0.0 if @name == Mime::ALL # default wilcard match to end of list
|
69
|
+
@q = ((q || 1.0).to_f * 100).to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_s
|
73
|
+
@name
|
74
|
+
end
|
75
|
+
|
76
|
+
def <=>(item)
|
77
|
+
result = item.q <=> q
|
78
|
+
result = order <=> item.order if result == 0
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def ==(item)
|
83
|
+
name == (item.respond_to?(:name) ? item.name : item)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class << self
|
88
|
+
def lookup(string)
|
89
|
+
LOOKUP[string]
|
90
|
+
end
|
91
|
+
|
92
|
+
def lookup_by_extension(extension)
|
93
|
+
EXTENSION_LOOKUP[extension.to_s]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for
|
97
|
+
# rendering different HTML versions depending on the user agent, like an iPhone.
|
98
|
+
def register_alias(string, symbol, extension_synonyms = [])
|
99
|
+
register(string, symbol, [], extension_synonyms, true)
|
100
|
+
end
|
101
|
+
|
102
|
+
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
103
|
+
Mime.instance_eval { const_set symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms) }
|
104
|
+
|
105
|
+
SET << Mime.const_get(symbol.to_s.upcase)
|
106
|
+
|
107
|
+
([string] + mime_type_synonyms).each { |str| LOOKUP[str] = SET.last } unless skip_lookup
|
108
|
+
([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last }
|
109
|
+
end
|
110
|
+
|
111
|
+
def parse(accept_header)
|
112
|
+
if accept_header !~ /,/
|
113
|
+
[Mime::Type.lookup(accept_header)]
|
114
|
+
else
|
115
|
+
# keep track of creation order to keep the subsequent sort stable
|
116
|
+
list = []
|
117
|
+
accept_header.split(/,/).each_with_index do |header, index|
|
118
|
+
params, q = header.split(/;\s*q=/)
|
119
|
+
if params
|
120
|
+
params.strip!
|
121
|
+
list << AcceptItem.new(index, params, q) unless params.empty?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
list.sort!
|
125
|
+
|
126
|
+
# Take care of the broken text/xml entry by renaming or deleting it
|
127
|
+
text_xml = list.index("text/xml")
|
128
|
+
app_xml = list.index(Mime::XML.to_s)
|
129
|
+
|
130
|
+
if text_xml && app_xml
|
131
|
+
# set the q value to the max of the two
|
132
|
+
list[app_xml].q = [list[text_xml].q, list[app_xml].q].max
|
133
|
+
|
134
|
+
# make sure app_xml is ahead of text_xml in the list
|
135
|
+
if app_xml > text_xml
|
136
|
+
list[app_xml], list[text_xml] = list[text_xml], list[app_xml]
|
137
|
+
app_xml, text_xml = text_xml, app_xml
|
138
|
+
end
|
139
|
+
|
140
|
+
# delete text_xml from the list
|
141
|
+
list.delete_at(text_xml)
|
142
|
+
|
143
|
+
elsif text_xml
|
144
|
+
list[text_xml].name = Mime::XML.to_s
|
145
|
+
end
|
146
|
+
|
147
|
+
# Look for more specific XML-based types and sort them ahead of app/xml
|
148
|
+
|
149
|
+
if app_xml
|
150
|
+
idx = app_xml
|
151
|
+
app_xml_type = list[app_xml]
|
152
|
+
|
153
|
+
while(idx < list.length)
|
154
|
+
type = list[idx]
|
155
|
+
break if type.q < app_xml_type.q
|
156
|
+
if type.name =~ /\+xml$/
|
157
|
+
list[app_xml], list[idx] = list[idx], list[app_xml]
|
158
|
+
app_xml = idx
|
159
|
+
end
|
160
|
+
idx += 1
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
165
|
+
list
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def initialize(string, symbol = nil, synonyms = [])
|
171
|
+
@symbol, @synonyms = symbol, synonyms
|
172
|
+
@string = string
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_s
|
176
|
+
@string
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_str
|
180
|
+
to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_sym
|
184
|
+
@symbol || @string.to_sym
|
185
|
+
end
|
186
|
+
|
187
|
+
def ===(list)
|
188
|
+
if list.is_a?(Array)
|
189
|
+
(@synonyms + [ self ]).any? { |synonym| list.include?(synonym) }
|
190
|
+
else
|
191
|
+
super
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def ==(mime_type)
|
196
|
+
return false if mime_type.blank?
|
197
|
+
(@synonyms + [ self ]).any? do |synonym|
|
198
|
+
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def =~(mime_type)
|
203
|
+
return false if mime_type.blank?
|
204
|
+
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
205
|
+
(@synonyms + [ self ]).any? do |synonym|
|
206
|
+
synonym.to_s =~ regexp
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
|
211
|
+
# ActionController::RequestForgeryProtection.
|
212
|
+
def verify_request?
|
213
|
+
@@browser_generated_types.include?(to_sym)
|
214
|
+
end
|
215
|
+
|
216
|
+
def html?
|
217
|
+
@@html_types.include?(to_sym) || @string =~ /html/
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
def method_missing(method, *args)
|
222
|
+
if method.to_s =~ /(\w+)\?$/
|
223
|
+
$1.downcase.to_sym == to_sym
|
224
|
+
else
|
225
|
+
super
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
require 'dependency/mime_types'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Build list of Mime types for HTTP responses
|
2
|
+
# http://www.iana.org/assignments/media-types/
|
3
|
+
|
4
|
+
Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
|
5
|
+
Mime::Type.register "text/plain", :text, [], %w(txt)
|
6
|
+
Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
|
7
|
+
Mime::Type.register "text/css", :css
|
8
|
+
Mime::Type.register "text/calendar", :ics
|
9
|
+
Mime::Type.register "text/csv", :csv
|
10
|
+
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
|
11
|
+
Mime::Type.register "application/rss+xml", :rss
|
12
|
+
Mime::Type.register "application/atom+xml", :atom
|
13
|
+
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
|
14
|
+
|
15
|
+
Mime::Type.register "multipart/form-data", :multipart_form
|
16
|
+
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
|
17
|
+
|
18
|
+
# http://www.ietf.org/rfc/rfc4627.txt
|
19
|
+
# http://www.json.org/JSONRequest.html
|
20
|
+
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
|
21
|
+
|
22
|
+
# Create Mime::ALL but do not add it to the SET.
|
23
|
+
Mime::ALL = Mime::Type.new("*/*", :all, [])
|
data/lib/hashblue/api.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'httparty'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
# By using autoload rather than require, we only use our fallback
|
6
|
+
# dependency if Mime hasn't been loaded elsewhere
|
7
|
+
autoload :Mime, 'dependency/mime_type'
|
8
|
+
|
9
|
+
module Hashblue
|
10
|
+
|
11
|
+
# = It's the Hashblue API gem
|
12
|
+
#
|
13
|
+
# == Connecting
|
14
|
+
#
|
15
|
+
# Hashblue API requires ActiveSupport; if this isn't already loaded, you'll need
|
16
|
+
# to ensure that it is available - either by requiring rubygems, or ensuring
|
17
|
+
# it is in the +LOAD_PATH+ already.
|
18
|
+
#
|
19
|
+
# To connect to the Hashblue API, you need to set the base URL, and provide
|
20
|
+
# your credentials (you can find these in your hashblue.com account). For
|
21
|
+
# example:
|
22
|
+
#
|
23
|
+
# require 'active_support/all' # unless you have already loaded it
|
24
|
+
# require 'hashblue/api'
|
25
|
+
#
|
26
|
+
# Hashblue::API.base_uri "https://api.hashblue.apigee.com"
|
27
|
+
# Hashblue::API.basic_auth "dave@example.com", "yourapikey"
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# == Using the API
|
31
|
+
#
|
32
|
+
# Everything is loaded via your subscriber:
|
33
|
+
#
|
34
|
+
# subscriber = Hashblue::API::Subscriber.find("yourapikey")
|
35
|
+
#
|
36
|
+
# Once you have this, you can load all messages, all contacts, or all
|
37
|
+
# messages for a specific contact:
|
38
|
+
#
|
39
|
+
# all_messages = subscriber.messages
|
40
|
+
# all_contacts = subscriber.contacts
|
41
|
+
# messages_between_me_and_a_contact = all_contacts.first.messages
|
42
|
+
#
|
43
|
+
# == Interacting with messages
|
44
|
+
#
|
45
|
+
# It's simple to delete a message:
|
46
|
+
#
|
47
|
+
# all_messages.first.delete
|
48
|
+
#
|
49
|
+
# This message is now deleted. You can see a list of all deleted messages
|
50
|
+
# via the subscriber:
|
51
|
+
#
|
52
|
+
# subscriber.deleted_messages
|
53
|
+
module API
|
54
|
+
autoload :Contact, 'hashblue/api/contact'
|
55
|
+
autoload :Message, 'hashblue/api/message'
|
56
|
+
autoload :Model, 'hashblue/api/model'
|
57
|
+
autoload :Request, 'hashblue/api/request'
|
58
|
+
autoload :Subscriber, 'hashblue/api/subscriber'
|
59
|
+
autoload :Error, 'hashblue/api/error'
|
60
|
+
autoload :TestHelper, 'hashblue/api/test_helper'
|
61
|
+
|
62
|
+
# Raised when the API fails to respond with a timeout. The timeout
|
63
|
+
# can be set using Hashblue::API.timeout
|
64
|
+
class NotRespondingError < StandardError; end
|
65
|
+
# Raised when the API responded in a way that we couldn't handle.
|
66
|
+
class BadResponseError < Hashblue::API::Error; end
|
67
|
+
# Raised when the object requested cannot be found.
|
68
|
+
class NotFoundError < Hashblue::API::Error; end
|
69
|
+
# Raised when the object requested is not available given the
|
70
|
+
# credentials used; most often is is because a Contact or Message
|
71
|
+
# belongs to a different Subscriber
|
72
|
+
class AccessDeniedError < Hashblue::API::Error
|
73
|
+
def status
|
74
|
+
:unauthorized
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Sets the timeout used before raising an error.
|
79
|
+
def self.timeout(value)
|
80
|
+
default_options[:timeout] = value
|
81
|
+
end
|
82
|
+
|
83
|
+
include HTTParty
|
84
|
+
extend Request
|
85
|
+
|
86
|
+
base_uri "https://api.hashblue.apigee.com"
|
87
|
+
timeout 5
|
88
|
+
end
|
89
|
+
end
|