amee 2.0.25
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/COPYING +19 -0
- data/README +106 -0
- data/amee.example.yml +12 -0
- data/bin/ameesh +30 -0
- data/examples/create_profile.rb +27 -0
- data/examples/create_profile_item.rb +33 -0
- data/examples/list_profiles.rb +29 -0
- data/examples/view_data_category.rb +40 -0
- data/examples/view_data_item.rb +37 -0
- data/init.rb +1 -0
- data/lib/amee.rb +63 -0
- data/lib/amee/connection.rb +236 -0
- data/lib/amee/data_category.rb +196 -0
- data/lib/amee/data_item.rb +218 -0
- data/lib/amee/data_item_value.rb +167 -0
- data/lib/amee/data_object.rb +11 -0
- data/lib/amee/drill_down.rb +102 -0
- data/lib/amee/exceptions.rb +27 -0
- data/lib/amee/item_definition.rb +158 -0
- data/lib/amee/object.rb +21 -0
- data/lib/amee/pager.rb +59 -0
- data/lib/amee/profile.rb +108 -0
- data/lib/amee/profile_category.rb +514 -0
- data/lib/amee/profile_item.rb +374 -0
- data/lib/amee/profile_item_value.rb +106 -0
- data/lib/amee/profile_object.rb +20 -0
- data/lib/amee/rails.rb +82 -0
- data/lib/amee/shell.rb +90 -0
- data/lib/amee/user.rb +111 -0
- data/lib/amee/version.rb +10 -0
- data/rails/init.rb +12 -0
- metadata +104 -0
data/COPYING
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 James Smith (james@floppy.org.uk)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
== AMEE-Ruby
|
2
|
+
|
3
|
+
A gem to provide a Ruby interface to the AMEE carbon calculator (http://amee.cc)
|
4
|
+
|
5
|
+
Licensed under the MIT license (See COPYING file for details)
|
6
|
+
|
7
|
+
Author: James Smith (james@floppy.org.uk / http://www.floppy.org.uk)
|
8
|
+
|
9
|
+
Homepage: http://github.com/Floppy/amee-ruby
|
10
|
+
|
11
|
+
Documentation: http://docs.github.com/Floppy/amee-ruby
|
12
|
+
|
13
|
+
== INSTALLATION
|
14
|
+
|
15
|
+
1) Enable gems from github, if you haven't already done so (rubygems >= 1.2):
|
16
|
+
> sudo gem sources -a http://gems.github.com
|
17
|
+
|
18
|
+
2) Install gem
|
19
|
+
> sudo gem install Floppy-amee
|
20
|
+
|
21
|
+
== IMPORTANT CHANGES in 2.0.25
|
22
|
+
|
23
|
+
If you are using the $amee connection in your Rails apps, this is now deprecated
|
24
|
+
and will be removed in future releases. See the "Rails" section below for details
|
25
|
+
of what you should use instead.
|
26
|
+
|
27
|
+
== USAGE
|
28
|
+
|
29
|
+
Currently, you can read DataCategories, DataItems and DataItemValues. See
|
30
|
+
examples/view_data_*.rb for simple usage examples. You can also get the list
|
31
|
+
of available Profiles, and create and delete them. See examples/list_profiles.rb
|
32
|
+
and examples/create_profile.rb for details. You can also load ProfileCategories,
|
33
|
+
and load, create and update ProfileItems.
|
34
|
+
|
35
|
+
The gem will use the AMEE JSON API if the JSON gem is installed on the local
|
36
|
+
system. Otherwise the XML API will be used.
|
37
|
+
|
38
|
+
== SUPPORT
|
39
|
+
Create Read Update Delete
|
40
|
+
DataCategories N Y N N
|
41
|
+
DataItems N Y N N
|
42
|
+
DataItemValues N Y N Y
|
43
|
+
Profile List - Y - -
|
44
|
+
Profiles Y - - Y
|
45
|
+
ProfileCategories - Y - -
|
46
|
+
- drilldown - Y - -
|
47
|
+
ProfileItems Y Y Y Y
|
48
|
+
|
49
|
+
== INTERACTIVE SHELL
|
50
|
+
|
51
|
+
You can use the 'ameesh' app to interactively explore the AMEE data area. Run
|
52
|
+
'ameesh -u USERNAME -p PASSWORD -s SERVER' to try it out. Source code for this
|
53
|
+
tool is in bin/ameesh and lib/amee/shell.rb. Profiles are not accessible through
|
54
|
+
this interface yet.
|
55
|
+
|
56
|
+
== RAILS
|
57
|
+
|
58
|
+
This gem can also be used as a Rails plugin. You can either extract it into
|
59
|
+
vendor/plugins, or use the new-style config.gem command in environment.rb. For
|
60
|
+
example:
|
61
|
+
|
62
|
+
config.gem "Floppy-amee", :lib => "amee", :source => "http://gems.github.com", :version => '>= 0.3.0'
|
63
|
+
|
64
|
+
If you copy amee.example.yml from the gem source directory to amee.yml in your
|
65
|
+
app's config directory, a persistent AMEE connection will be available from
|
66
|
+
AMEE::Rails#connection, which you can use anywhere. In your controllers, you can
|
67
|
+
also use the global_amee_connection function to access the same global connection.
|
68
|
+
|
69
|
+
data = AMEE::Data::Category.root(global_amee_connection)
|
70
|
+
|
71
|
+
If you do not use this facility, you will have to create your own connection
|
72
|
+
objects and manage them yourself, which you can do using AMEE::Connection#new
|
73
|
+
|
74
|
+
There is a helper for ActiveRecord models which should be linked to an AMEE profile.
|
75
|
+
By adding:
|
76
|
+
|
77
|
+
has_amee_profile
|
78
|
+
|
79
|
+
to your model, and by adding an amee_profile:string field to the model in the
|
80
|
+
database, an AMEE profile will be automatically created and destroyed with your
|
81
|
+
model. By overriding the function amee_save in your model, you can store data in
|
82
|
+
AMEE when your model is saved.
|
83
|
+
|
84
|
+
== CACHING
|
85
|
+
|
86
|
+
The AMEE::Connection object implements an optional cache for GET requests. This is
|
87
|
+
currently a versy simple implementation which caches the result of all GET requests
|
88
|
+
until a POST, PUT, or DELETE is executed, at which point the cache is cleared. To
|
89
|
+
enable caching, set the enable_caching parameter of AMEE::Connection.new to true.
|
90
|
+
Caching is disabled by default.
|
91
|
+
|
92
|
+
== UPGRADING TO VERSION > 2
|
93
|
+
|
94
|
+
There are a few changes to the API exposed by this gem for version 2. The main
|
95
|
+
ones are:
|
96
|
+
|
97
|
+
1) AMEE::Connection#new takes a hash of options instead of an explicit parameter list.
|
98
|
+
Whereas before you would have used new(server, username, password, use_json, enable_cache, enable_debug)
|
99
|
+
you would now use new(server, username, password, :format => :json, :enable_caching => true, :enable_debug => true)
|
100
|
+
|
101
|
+
2) Many get functions take a hash of options instead of explicit date and itemsPerPage parameters.
|
102
|
+
get(... , :start_date => {your_date}, :itemsPerPage => 20)
|
103
|
+
|
104
|
+
3) total_amount_per_month functions have been replaced with total_amount. There are also
|
105
|
+
total_amount_unit and total_amount_per_unit functions which give the units that the total
|
106
|
+
amount is in.
|
data/amee.example.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
development:
|
2
|
+
server: stage.amee.com
|
3
|
+
username: your_amee_username
|
4
|
+
password: your_amee_password
|
5
|
+
test:
|
6
|
+
server: stage.amee.com
|
7
|
+
username: your_amee_username
|
8
|
+
password: your_amee_password
|
9
|
+
production:
|
10
|
+
server: live.amee.com
|
11
|
+
username: your_amee_username
|
12
|
+
password: your_amee_password
|
data/bin/ameesh
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
shell_lib = File.dirname(__FILE__) + '/../lib/amee/shell'
|
4
|
+
irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
# Command-line options - get username, password, and server
|
8
|
+
options = {}
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.on("-u USERNAME", "AMEE username") do |u|
|
11
|
+
options[:username] = u
|
12
|
+
end
|
13
|
+
opts.on("-p PASSWORD", "AMEE password") do |p|
|
14
|
+
options[:password] = p
|
15
|
+
end
|
16
|
+
opts.on("-s SERVER", "AMEE server") do |s|
|
17
|
+
options[:server] = s
|
18
|
+
end
|
19
|
+
end.parse!
|
20
|
+
|
21
|
+
# Set environment variables for irb
|
22
|
+
ENV['AMEE_SERVER'] = options[:server]
|
23
|
+
ENV['AMEE_USERNAME'] = options[:username]
|
24
|
+
ENV['AMEE_PASSWORD'] = options[:password]
|
25
|
+
|
26
|
+
if options[:server].nil? || options[:username].nil? || options[:password].nil?
|
27
|
+
puts "Please provide connection details. Run 'ameesh --help' for details."
|
28
|
+
else
|
29
|
+
exec "#{irb_name} -r #{shell_lib} --simple-prompt"
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
dir = File.dirname(__FILE__) + '/../lib'
|
2
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
3
|
+
|
4
|
+
#require 'rubygems'
|
5
|
+
require 'amee'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
# Command-line options - get username, password, and server
|
9
|
+
options = {}
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.on("-u", "--username USERNAME", "AMEE username") do |u|
|
12
|
+
options[:username] = u
|
13
|
+
end
|
14
|
+
opts.on("-p", "--password PASSWORD", "AMEE password") do |p|
|
15
|
+
options[:password] = p
|
16
|
+
end
|
17
|
+
opts.on("-s", "--server SERVER", "AMEE server") do |s|
|
18
|
+
options[:server] = s
|
19
|
+
end
|
20
|
+
end.parse!
|
21
|
+
|
22
|
+
# Connect
|
23
|
+
connection = AMEE::Connection.new(options[:server], options[:username], options[:password])
|
24
|
+
|
25
|
+
# Create a new profile
|
26
|
+
profile = AMEE::Profile::Profile.create(connection)
|
27
|
+
puts "#{profile.uid} created"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
dir = File.dirname(__FILE__) + '/../lib'
|
2
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
3
|
+
|
4
|
+
#require 'rubygems'
|
5
|
+
require 'amee'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
# Command-line options - get username, password, and server
|
9
|
+
options = {}
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.on("-u", "--username USERNAME", "AMEE username") do |u|
|
12
|
+
options[:username] = u
|
13
|
+
end
|
14
|
+
opts.on("-p", "--password PASSWORD", "AMEE password") do |p|
|
15
|
+
options[:password] = p
|
16
|
+
end
|
17
|
+
opts.on("-s", "--server SERVER", "AMEE server") do |s|
|
18
|
+
options[:server] = s
|
19
|
+
end
|
20
|
+
end.parse!
|
21
|
+
|
22
|
+
# Connect
|
23
|
+
connection = AMEE::Connection.new(options[:server], options[:username], options[:password])
|
24
|
+
|
25
|
+
# Create a new profile item
|
26
|
+
category = AMEE::Profile::Category.get(connection, ARGV[0])
|
27
|
+
puts "loaded category #{category.name}"
|
28
|
+
item = AMEE::Profile::Item.create(category, ARGV[1])
|
29
|
+
if item
|
30
|
+
puts "created item in #{category.name} OK"
|
31
|
+
else
|
32
|
+
puts "error creating item in #{category.name}"
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'amee'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# Command-line options - get username, password, and server
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.on("-u", "--username USERNAME", "AMEE username") do |u|
|
9
|
+
options[:username] = u
|
10
|
+
end
|
11
|
+
opts.on("-p", "--password PASSWORD", "AMEE password") do |p|
|
12
|
+
options[:password] = p
|
13
|
+
end
|
14
|
+
opts.on("-s", "--server SERVER", "AMEE server") do |s|
|
15
|
+
options[:server] = s
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
# Connect
|
20
|
+
connection = AMEE::Connection.new(options[:server], options[:username], options[:password])
|
21
|
+
|
22
|
+
# List all available profiles
|
23
|
+
profiles = AMEE::Profile::Profile.list(connection)
|
24
|
+
puts "#{profiles.size} #{profiles.size == 1 ? "profile" : "profiles"} available in AMEE:"
|
25
|
+
profiles.each do |p|
|
26
|
+
puts p.uid
|
27
|
+
end
|
28
|
+
|
29
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'amee'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# Command-line options - get username, password, and server
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.on("-u", "--username USERNAME", "AMEE username") do |u|
|
9
|
+
options[:username] = u
|
10
|
+
end
|
11
|
+
opts.on("-p", "--password PASSWORD", "AMEE password") do |p|
|
12
|
+
options[:password] = p
|
13
|
+
end
|
14
|
+
opts.on("-s", "--server SERVER", "AMEE server") do |s|
|
15
|
+
options[:server] = s
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
# Connect
|
20
|
+
connection = AMEE::Connection.new(options[:server], options[:username], options[:password])
|
21
|
+
|
22
|
+
# For each path in arg list, show details
|
23
|
+
ARGV.each do |path|
|
24
|
+
cat = AMEE::Data::Category.get(connection, path)
|
25
|
+
puts "---------------------"
|
26
|
+
puts "Category: #{cat.name}"
|
27
|
+
puts "Path: #{cat.full_path}"
|
28
|
+
puts "UID: #{cat.uid}"
|
29
|
+
puts "Subcategories:"
|
30
|
+
cat.children.each do |c|
|
31
|
+
puts " - #{c[:path]} (#{c[:name]})"
|
32
|
+
end
|
33
|
+
puts "Items:"
|
34
|
+
cat.items.each do |i|
|
35
|
+
puts " - #{i[:path]} (#{i[:label]})"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'amee'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# Command-line options - get username, password, and server
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.on("-u", "--username USERNAME", "AMEE username") do |u|
|
9
|
+
options[:username] = u
|
10
|
+
end
|
11
|
+
opts.on("-p", "--password PASSWORD", "AMEE password") do |p|
|
12
|
+
options[:password] = p
|
13
|
+
end
|
14
|
+
opts.on("-s", "--server SERVER", "AMEE server") do |s|
|
15
|
+
options[:server] = s
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
# Connect
|
20
|
+
connection = AMEE::Connection.new(options[:server], options[:username], options[:password])
|
21
|
+
|
22
|
+
# For each path in arg list, show details
|
23
|
+
ARGV.each do |path|
|
24
|
+
cat = AMEE::Data::Item.get(connection, path)
|
25
|
+
puts "---------------------"
|
26
|
+
puts "Name: #{cat.name}"
|
27
|
+
puts "Path: #{cat.full_path}"
|
28
|
+
puts "Label: #{cat.label}"
|
29
|
+
puts "UID: #{cat.uid}"
|
30
|
+
puts "Values:"
|
31
|
+
cat.values.each do |v|
|
32
|
+
puts " - #{v[:name]}: #{v[:value]}"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/rails/init"
|
data/lib/amee.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'activesupport'
|
3
|
+
|
4
|
+
# We don't NEED the JSON gem, but if it's available, use it.
|
5
|
+
begin
|
6
|
+
require 'json'
|
7
|
+
rescue LoadError
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
class String
|
12
|
+
def is_json?
|
13
|
+
slice(0,1) == '{'
|
14
|
+
end
|
15
|
+
def is_v2_json?
|
16
|
+
is_json? && match('"apiVersion"\s?:\s?"2.0"')
|
17
|
+
end
|
18
|
+
def is_xml?
|
19
|
+
slice(0,5) == '<?xml'
|
20
|
+
end
|
21
|
+
def is_v2_xml?
|
22
|
+
is_xml? && include?('<Resources xmlns="http://schemas.amee.cc/2.0">')
|
23
|
+
end
|
24
|
+
def is_v2_atom?
|
25
|
+
is_xml? && (include?('<feed ') || include?('<entry ')) && include?('xmlns:amee="http://schemas.amee.cc/2.0"')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'amee/version'
|
30
|
+
require 'amee/exceptions'
|
31
|
+
require 'amee/connection'
|
32
|
+
require 'amee/object'
|
33
|
+
require 'amee/data_object'
|
34
|
+
require 'amee/profile_object'
|
35
|
+
require 'amee/data_category'
|
36
|
+
require 'amee/data_item'
|
37
|
+
require 'amee/data_item_value'
|
38
|
+
require 'amee/profile'
|
39
|
+
require 'amee/profile_category'
|
40
|
+
require 'amee/profile_item'
|
41
|
+
require 'amee/profile_item_value'
|
42
|
+
require 'amee/drill_down'
|
43
|
+
require 'amee/pager'
|
44
|
+
require 'amee/item_definition'
|
45
|
+
require 'amee/user'
|
46
|
+
|
47
|
+
class Date
|
48
|
+
def amee1_date
|
49
|
+
strftime("%Y%m%d")
|
50
|
+
end
|
51
|
+
def amee1_month
|
52
|
+
strftime("%Y%m")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Time
|
57
|
+
def amee1_date
|
58
|
+
strftime("%Y%m%d")
|
59
|
+
end
|
60
|
+
def amee1_month
|
61
|
+
strftime("%Y%m")
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module AMEE
|
4
|
+
class Connection
|
5
|
+
|
6
|
+
def initialize(server, username, password, options = {})
|
7
|
+
unless options.is_a?(Hash)
|
8
|
+
raise AMEE::ArgumentError.new("Fourth argument must be a hash of options!")
|
9
|
+
end
|
10
|
+
@server = server
|
11
|
+
@username = username
|
12
|
+
@password = password
|
13
|
+
@auth_token = nil
|
14
|
+
@format = options[:format] || (defined?(JSON) ? :json : :xml)
|
15
|
+
if !valid?
|
16
|
+
raise "You must supply connection details - server, username and password are all required!"
|
17
|
+
end
|
18
|
+
@enable_caching = options[:enable_caching]
|
19
|
+
if @enable_caching
|
20
|
+
$cache ||= {}
|
21
|
+
end
|
22
|
+
# Make connection to server
|
23
|
+
@http = Net::HTTP.new(@server)
|
24
|
+
@http.read_timeout = 5
|
25
|
+
@http.set_debug_output($stdout) if options[:enable_debug]
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :format
|
29
|
+
attr_reader :server
|
30
|
+
attr_reader :username
|
31
|
+
attr_reader :password
|
32
|
+
|
33
|
+
def timeout
|
34
|
+
@http.read_timeout
|
35
|
+
end
|
36
|
+
|
37
|
+
def timeout=(t)
|
38
|
+
@http.read_timeout = t
|
39
|
+
end
|
40
|
+
|
41
|
+
def version
|
42
|
+
authenticate if @version.nil?
|
43
|
+
@version
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid?
|
47
|
+
@username && @password && @server
|
48
|
+
end
|
49
|
+
|
50
|
+
def authenticated?
|
51
|
+
!@auth_token.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def get(path, data = {})
|
55
|
+
# Allow format override
|
56
|
+
format = data.delete(:format) || @format
|
57
|
+
# Create URL parameters
|
58
|
+
params = []
|
59
|
+
data.each_pair do |key, value|
|
60
|
+
params << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
|
61
|
+
end
|
62
|
+
if params.size > 0
|
63
|
+
path += "?#{params.join('&')}"
|
64
|
+
end
|
65
|
+
# Send request
|
66
|
+
return $cache[path] if @enable_caching and $cache[path]
|
67
|
+
response = do_request(Net::HTTP::Get.new(path), format)
|
68
|
+
$cache[path] = response if @enable_caching
|
69
|
+
return response
|
70
|
+
end
|
71
|
+
|
72
|
+
def post(path, data = {})
|
73
|
+
# Allow format override
|
74
|
+
format = data.delete(:format) || @format
|
75
|
+
# Clear cache
|
76
|
+
clear_cache
|
77
|
+
# Create POST request
|
78
|
+
post = Net::HTTP::Post.new(path)
|
79
|
+
body = []
|
80
|
+
data.each_pair do |key, value|
|
81
|
+
body << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
|
82
|
+
end
|
83
|
+
post.body = body.join '&'
|
84
|
+
# Send request
|
85
|
+
do_request(post, format)
|
86
|
+
end
|
87
|
+
|
88
|
+
def raw_post(path, body, options = {})
|
89
|
+
# Allow format override
|
90
|
+
format = options.delete(:format) || @format
|
91
|
+
# Clear cache
|
92
|
+
clear_cache
|
93
|
+
# Create POST request
|
94
|
+
post = Net::HTTP::Post.new(path)
|
95
|
+
post['Content-type'] = options[:content_type] || content_type(format)
|
96
|
+
post.body = body
|
97
|
+
# Send request
|
98
|
+
do_request(post, format)
|
99
|
+
end
|
100
|
+
|
101
|
+
def put(path, data = {})
|
102
|
+
# Allow format override
|
103
|
+
format = data.delete(:format) || @format
|
104
|
+
# Clear cache
|
105
|
+
clear_cache
|
106
|
+
# Create PUT request
|
107
|
+
put = Net::HTTP::Put.new(path)
|
108
|
+
body = []
|
109
|
+
data.each_pair do |key, value|
|
110
|
+
body << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
|
111
|
+
end
|
112
|
+
put.body = body.join '&'
|
113
|
+
# Send request
|
114
|
+
do_request(put, format)
|
115
|
+
end
|
116
|
+
|
117
|
+
def raw_put(path, body, options = {})
|
118
|
+
# Allow format override
|
119
|
+
format = options.delete(:format) || @format
|
120
|
+
# Clear cache
|
121
|
+
clear_cache
|
122
|
+
# Create PUT request
|
123
|
+
put = Net::HTTP::Put.new(path)
|
124
|
+
put['Content-type'] = options[:content_type] || content_type(format)
|
125
|
+
put.body = body
|
126
|
+
# Send request
|
127
|
+
do_request(put, format)
|
128
|
+
end
|
129
|
+
|
130
|
+
def delete(path)
|
131
|
+
clear_cache
|
132
|
+
# Create DELETE request
|
133
|
+
delete = Net::HTTP::Delete.new(path)
|
134
|
+
# Send request
|
135
|
+
do_request(delete)
|
136
|
+
end
|
137
|
+
|
138
|
+
def authenticate
|
139
|
+
response = nil
|
140
|
+
post = Net::HTTP::Post.new("/auth/signIn")
|
141
|
+
post.body = "username=#{@username}&password=#{@password}"
|
142
|
+
post['Accept'] = content_type(:xml)
|
143
|
+
response = @http.request(post)
|
144
|
+
@auth_token = response['authToken']
|
145
|
+
unless authenticated?
|
146
|
+
raise AMEE::AuthFailed.new("Authentication failed. Please check your username and password.")
|
147
|
+
end
|
148
|
+
# Detect API version
|
149
|
+
if response.body.is_json?
|
150
|
+
@version = JSON.parse(response.body)["user"]["apiVersion"].to_f
|
151
|
+
elsif response.body.is_xml?
|
152
|
+
@version = REXML::Document.new(response.body).elements['Resources'].elements['SignInResource'].elements['User'].elements['ApiVersion'].text.to_f
|
153
|
+
else
|
154
|
+
@version = 1.0
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
protected
|
159
|
+
|
160
|
+
def content_type(format = @format)
|
161
|
+
case format
|
162
|
+
when :xml
|
163
|
+
return 'application/xml'
|
164
|
+
when :json
|
165
|
+
return 'application/json'
|
166
|
+
when :atom
|
167
|
+
return 'application/atom+xml'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def redirect?(response)
|
172
|
+
response.code == '301' || response.code == '302'
|
173
|
+
end
|
174
|
+
|
175
|
+
def response_ok?(response)
|
176
|
+
case response.code
|
177
|
+
when '200', '201'
|
178
|
+
return true
|
179
|
+
when '403'
|
180
|
+
raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation. AMEE Response: #{response.body}")
|
181
|
+
when '401'
|
182
|
+
authenticate
|
183
|
+
return false
|
184
|
+
when '400'
|
185
|
+
if response.body.include? "would have resulted in a duplicate resource being created"
|
186
|
+
raise AMEE::DuplicateResource.new("The specified resource already exists. This is most often caused by creating an item that overlaps another in time. AMEE Response: #{response.body}")
|
187
|
+
else
|
188
|
+
raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}. AMEE Response: #{response.body}")
|
189
|
+
end
|
190
|
+
else
|
191
|
+
raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}. AMEE Response: #{response.body}")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def do_request(request, format = @format)
|
196
|
+
# Open HTTP connection
|
197
|
+
@http.start
|
198
|
+
# Do request
|
199
|
+
begin
|
200
|
+
response = send_request(request, format)
|
201
|
+
end while !response_ok?(response)
|
202
|
+
# Return response
|
203
|
+
return response
|
204
|
+
rescue SocketError
|
205
|
+
raise AMEE::ConnectionFailed.new("Connection failed. Check server name or network connection.")
|
206
|
+
ensure
|
207
|
+
# Close HTTP connection
|
208
|
+
@http.finish if @http.started?
|
209
|
+
end
|
210
|
+
|
211
|
+
def send_request(request, format = @format)
|
212
|
+
# Set auth token in cookie (and header just in case someone's stripping cookies)
|
213
|
+
request['Cookie'] = "authToken=#{@auth_token}"
|
214
|
+
request['authToken'] = @auth_token
|
215
|
+
# Set accept header
|
216
|
+
request['Accept'] = content_type(format)
|
217
|
+
# Do the business
|
218
|
+
response = @http.request(request)
|
219
|
+
# Handle 404s
|
220
|
+
if response.code == '404'
|
221
|
+
raise AMEE::NotFound.new("URL doesn't exist on server.")
|
222
|
+
end
|
223
|
+
# Done
|
224
|
+
response
|
225
|
+
end
|
226
|
+
|
227
|
+
public
|
228
|
+
|
229
|
+
def clear_cache
|
230
|
+
if @enable_caching
|
231
|
+
$cache = {}
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|