Floppy-amee 2.0.22 → 2.0.24

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 CHANGED
@@ -55,16 +55,16 @@ example:
55
55
 
56
56
  config.gem "Floppy-amee", :lib => "amee", :source => "http://gems.github.com", :version => '>= 0.3.0'
57
57
 
58
- The first time you run your app after installing the gem, a config/amee.yml file
59
- will be created. You should edit this file and add your AMEE username and
60
- password to it, as well as the server you want to connect to.
61
-
62
- Once that is all set up, you can use AMEE objects within Rails anywhere you like.
63
- There is a persistent AMEE connection available called $amee, which you can pass
64
- into the other objects to fetch data. For instance:
58
+ If you copy amee.example.yml from the gem source directory to amee.yml in your
59
+ app's config directory, a persistent AMEE connection available called $amee,
60
+ will be automatically set up for you, which you can pass into the other objects
61
+ to fetch data. For instance:
65
62
 
66
63
  data = AMEE::Data::Category.root($amee)
67
64
 
65
+ If you do not use this facility, you will have to create your own connection
66
+ objects and manage them yourself.
67
+
68
68
  There is a helper for ActiveRecord models which should be linked to an AMEE profile.
69
69
  By adding:
70
70
 
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/lib/amee.rb CHANGED
@@ -42,6 +42,7 @@ require 'amee/profile_item_value'
42
42
  require 'amee/drill_down'
43
43
  require 'amee/pager'
44
44
  require 'amee/item_definition'
45
+ require 'amee/user'
45
46
 
46
47
  class Date
47
48
  def amee1_date
@@ -178,6 +178,12 @@ module AMEE
178
178
  when '401'
179
179
  authenticate
180
180
  return false
181
+ when '400'
182
+ if response.body.include? "would have resulted in a duplicate resource being created"
183
+ 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}")
184
+ else
185
+ raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}. AMEE Response: #{response.body}")
186
+ end
181
187
  else
182
188
  raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}. AMEE Response: #{response.body}")
183
189
  end
@@ -81,9 +81,21 @@ module AMEE
81
81
  raise AMEE::BadData.new("Couldn't load DataCategory from XML data. Check that your URL is correct.\n#{xml}")
82
82
  end
83
83
 
84
- def self.get(connection, path, items_per_page = 10)
84
+ def self.get(connection, path, orig_options = {})
85
+ unless orig_options.is_a?(Hash)
86
+ raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
87
+ end
88
+ # Convert to AMEE options
89
+ options = orig_options.clone
90
+ if orig_options[:items_per_page]
91
+ options[:itemsPerPage] = orig_options[:items_per_page]
92
+ else
93
+ options[:itemsPerPage] = 10
94
+ end
95
+
85
96
  # Load data from path
86
- response = connection.get(path, :itemsPerPage => items_per_page).body
97
+ response = connection.get(path, options).body
98
+
87
99
  # Parse data from response
88
100
  if response.is_json?
89
101
  cat = Category.from_json(response)
@@ -161,6 +173,23 @@ module AMEE
161
173
  rescue
162
174
  raise AMEE::BadData.new("Couldn't delete DataCategory. Check that your information is correct.")
163
175
  end
176
+
177
+ def self.update(connection, path, options = {})
178
+ # Do we want to automatically fetch the item afterwards?
179
+ get_item = options.delete(:get_item)
180
+ get_item = true if get_item.nil?
181
+ # Go
182
+ response = connection.put(path, options)
183
+ if get_item
184
+ if response.body.empty?
185
+ return Category.get(connection, path)
186
+ else
187
+ return Category.parse(connection, response.body)
188
+ end
189
+ end
190
+ rescue
191
+ raise AMEE::BadData.new("Couldn't update Data Category. Check that your information is correct.")
192
+ end
164
193
 
165
194
  end
166
195
  end
@@ -18,7 +18,7 @@ module AMEE
18
18
  attr_reader :item_definition
19
19
  attr_reader :total_amount
20
20
  attr_reader :total_amount_unit
21
-
21
+
22
22
  def self.from_json(json)
23
23
  # Read JSON
24
24
  doc = JSON.parse(json)
@@ -111,6 +111,12 @@ module AMEE
111
111
  def self.get(connection, path, options = {})
112
112
  # Load data from path
113
113
  response = connection.get(path, options).body
114
+ AMEE::Data::Item.parse(connection, response)
115
+ rescue
116
+ raise AMEE::BadData.new("Couldn't load DataItem. Check that your URL is correct.\n#{response}")
117
+ end
118
+
119
+ def self.parse(connection, response)
114
120
  # Parse data from response
115
121
  if response.is_json?
116
122
  item = Item.from_json(response)
@@ -121,8 +127,6 @@ module AMEE
121
127
  item.connection = connection
122
128
  # Done
123
129
  return item
124
- rescue
125
- raise AMEE::BadData.new("Couldn't load DataItem. Check that your URL is correct.\n#{response}")
126
130
  end
127
131
 
128
132
  def self.create_batch_without_category(connection, category_path, items, options = {})
@@ -156,47 +160,54 @@ module AMEE
156
160
  unless options.is_a?(Hash)
157
161
  raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
158
162
  end
159
- # Set dates
160
- if options[:start_date] && connection.version < 2
161
- options[:validFrom] = options[:start_date].amee1_date
162
- elsif options[:start_date] && connection.version >= 2
163
- options[:startDate] = options[:start_date].xmlschema
164
- end
165
- options.delete(:start_date)
166
- if options[:end_date] && connection.version >= 2
167
- options[:endDate] = options[:end_date].xmlschema
168
- end
169
- options.delete(:end_date)
170
- if options[:duration] && connection.version >= 2
171
- options[:duration] = "PT#{options[:duration] * 86400}S"
172
- end
173
163
  # Create a data item!
174
164
  options[:newObjectType] = "DI"
175
165
  # Send data to path
176
166
  response = connection.post(path, options)
177
- # if response['Location']
178
- # location = response['Location'].match("http://.*?(/.*)")[1]
179
- # else
180
- # category = Category.parse(connection, response.body)
181
- # location = category.full_path + "/" + category.items[0][:path]
182
- # end
183
- # if get_item == true
184
- # get_options = {}
185
- # get_options[:format] = format if format
186
- # return AMEE::Data::Item.get(connection, location, get_options)
187
- # else
188
- # return location
189
- # end
167
+ if response['Location']
168
+ location = response['Location'].match("http://.*?(/.*)")[1]
169
+ else
170
+ category = Category.parse(connection, response.body)
171
+ location = category.full_path + "/" + category.items[0][:path]
172
+ end
173
+ if get_item == true
174
+ get_options = {}
175
+ get_options[:format] = format if format
176
+ return AMEE::Data::Item.get(connection, location, get_options)
177
+ else
178
+ return location
179
+ end
190
180
  rescue
191
181
  raise AMEE::BadData.new("Couldn't create DataItem. Check that your information is correct.\n#{response}")
192
182
  end
193
183
 
194
- def update(options = {})
195
- response = connection.put(full_path, options).body
184
+ def self.update(connection, path, options = {})
185
+ # Do we want to automatically fetch the item afterwards?
186
+ get_item = options.delete(:get_item)
187
+ get_item = true if get_item.nil?
188
+ # Go
189
+ response = connection.put(path, options)
190
+ if get_item
191
+ if response.body.empty?
192
+ return Item.get(connection, path)
193
+ else
194
+ return Item.parse(connection, response.body)
195
+ end
196
+ end
196
197
  rescue
197
198
  raise AMEE::BadData.new("Couldn't update DataItem. Check that your information is correct.\n#{response}")
198
199
  end
200
+
201
+ def update(options = {})
202
+ AMEE::Data::Item.update(connection, full_path, options)
203
+ end
199
204
 
205
+ def self.delete(connection, path)
206
+ connection.delete(path)
207
+ rescue
208
+ raise AMEE::BadData.new("Couldn't delete DataItem. Check that your information is correct.")
209
+ end
210
+
200
211
  def value(name_or_path_or_uid)
201
212
  val = values.find{ |x| x[:name] == name_or_path_or_uid || x[:path] == name_or_path_or_uid || x[:uid] == name_or_path_or_uid}
202
213
  val ? val[:value] : nil
@@ -7,6 +7,7 @@ module AMEE
7
7
  @type = data ? data[:type] : nil
8
8
  @from_profile = data ? data[:from_profile] : nil
9
9
  @from_data = data ? data[:from_data] : nil
10
+ @start_date = data ? data[:start_date] : nil
10
11
  super
11
12
  end
12
13
 
@@ -33,6 +34,10 @@ module AMEE
33
34
  @from_data
34
35
  end
35
36
 
37
+ def start_date
38
+ @start_date
39
+ end
40
+
36
41
  def self.from_json(json, path)
37
42
  # Read JSON
38
43
  doc = JSON.parse(json)['itemValue']
@@ -44,6 +49,7 @@ module AMEE
44
49
  data[:path] = path.gsub(/^\/data/, '')
45
50
  data[:value] = doc['value']
46
51
  data[:type] = doc['itemValueDefinition']['valueDefinition']['valueType']
52
+ data[:start_date] = DateTime.parse(doc['startDate']) rescue nil
47
53
  # Create object
48
54
  ItemValue.new(data)
49
55
  rescue
@@ -63,6 +69,7 @@ module AMEE
63
69
  data[:type] = REXML::XPath.first(doc, '/Resources/DataItemValueResource/ItemValue/ItemValueDefinition/ValueDefinition/ValueType').text
64
70
  data[:from_profile] = REXML::XPath.first(doc, '/Resources/DataItemValueResource/ItemValue/ItemValueDefinition/FromProfile').text == "true" ? true : false
65
71
  data[:from_data] = REXML::XPath.first(doc, '/Resources/DataItemValueResource/ItemValue/ItemValueDefinition/FromData').text == "true" ? true : false
72
+ data[:start_date] = DateTime.parse(REXML::XPath.first(doc, "/Resources/DataItemValueResource/ItemValue/StartDate").text) rescue nil
66
73
  # Create object
67
74
  ItemValue.new(data)
68
75
  rescue
@@ -74,6 +81,18 @@ module AMEE
74
81
  response = connection.get(path).body
75
82
  # Parse data from response
76
83
  data = {}
84
+ value = ItemValue.parse(connection, response, path)
85
+ # Done
86
+ return value
87
+ rescue
88
+ raise AMEE::BadData.new("Couldn't load DataItemValue. Check that your URL is correct.")
89
+ end
90
+
91
+ def save!
92
+ response = @connection.put(full_path, :value => value).body
93
+ end
94
+
95
+ def self.parse(connection, response, path)
77
96
  if response.is_json?
78
97
  value = ItemValue.from_json(response, path)
79
98
  else
@@ -86,11 +105,63 @@ module AMEE
86
105
  rescue
87
106
  raise AMEE::BadData.new("Couldn't load DataItemValue. Check that your URL is correct.\n#{response}")
88
107
  end
108
+
109
+ def self.create(data_item, options = {})
110
+ # Do we want to automatically fetch the item afterwards?
111
+ get_item = options.delete(:get_item)
112
+ get_item = true if get_item.nil?
113
+ # Store format if set
114
+ format = options[:format]
115
+ unless options.is_a?(Hash)
116
+ raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
117
+ end
118
+ # Set startDate
119
+ if (options[:start_date])
120
+ options[:startDate] = options[:start_date].xmlschema
121
+ options.delete(:start_date)
122
+ end
123
+
124
+ response = data_item.connection.post(data_item.full_path, options)
125
+ location = response['Location'].match("http://.*?(/.*)")[1]
89
126
 
90
- def save!
91
- response = @connection.put(full_path, :value => value).body
127
+ if get_item == true
128
+ get_options = {}
129
+ get_options[:format] = format if format
130
+ return AMEE::Data::ItemValue.get(data_item.connection, location)
131
+ else
132
+ return location
133
+ end
134
+ rescue
135
+ raise AMEE::BadData.new("Couldn't create DataItemValue. Check that your information is correct.")
92
136
  end
93
137
 
138
+ def self.update(connection, path, options = {})
139
+ # Do we want to automatically fetch the item afterwards?
140
+ get_item = options.delete(:get_item)
141
+ get_item = true if get_item.nil?
142
+ # Go
143
+ response = connection.put(path, options)
144
+ if get_item
145
+ if response.body.empty?
146
+ return AMEE::Data::ItemValue.get(connection, path)
147
+ else
148
+ return AMEE::Data::ItemValue.parse(connection, response.body)
149
+ end
150
+ end
151
+ rescue
152
+ raise AMEE::BadData.new("Couldn't update DataItemValue. Check that your information is correct.\n#{response}")
153
+ end
154
+
155
+ def update(options = {})
156
+ AMEE::Data::ItemValue.update(connection, full_path, options)
157
+ end
158
+
159
+ def self.delete(connection, path)
160
+ connection.delete(path)
161
+ rescue
162
+ raise AMEE::BadData.new("Couldn't delete DataItemValue. Check that your information is correct.")
163
+ end
164
+
94
165
  end
95
166
  end
96
- end
167
+ end
@@ -18,6 +18,9 @@ module AMEE
18
18
  class NotFound < Exception
19
19
  end
20
20
 
21
+ class DuplicateResource < Exception
22
+ end
23
+
21
24
  class UnknownError < Exception
22
25
  end
23
26
 
@@ -110,8 +110,19 @@ module AMEE
110
110
  raise AMEE::BadData.new("Couldn't load ItemDefinition. Check that your URL is correct.\n#{response}")
111
111
  end
112
112
 
113
- def update(options = {})
114
- response = connection.put(full_path, options).body
113
+ def self.update(connection, path, options = {})
114
+ # Do we want to automatically fetch the item afterwards?
115
+ get_item = options.delete(:get_item)
116
+ get_item = true if get_item.nil?
117
+ # Go
118
+ response = connection.put(path, options)
119
+ if get_item
120
+ if response.body.empty?
121
+ return ItemDefinition.get(connection, path)
122
+ else
123
+ return ItemDefinition.parse(connection, response.body)
124
+ end
125
+ end
115
126
  rescue
116
127
  raise AMEE::BadData.new("Couldn't update ItemDefinition. Check that your information is correct.\n#{response}")
117
128
  end
@@ -316,7 +316,7 @@ module AMEE
316
316
  options.delete(:start_date)
317
317
  if options[:end_date] && connection.version >= 2
318
318
  options[:endDate] = options[:end_date].xmlschema
319
- end
319
+ end
320
320
  options.delete(:end_date)
321
321
  if options[:duration] && connection.version >= 2
322
322
  options[:duration] = "PT#{options[:duration] * 86400}S"
data/lib/amee/user.rb ADDED
@@ -0,0 +1,111 @@
1
+ module AMEE
2
+ module Admin
3
+
4
+ class User < AMEE::Object
5
+
6
+ attr_reader :username
7
+ attr_reader :name
8
+ attr_reader :email
9
+ attr_reader :api_version
10
+ attr_reader :status
11
+
12
+ def initialize(data = {})
13
+ @username = data[:username]
14
+ @name = data[:name]
15
+ @email = data[:email]
16
+ @status = data[:status]
17
+ @api_version = data[:api_version].to_f rescue nil
18
+ @environment_uid = data[:environment_uid]
19
+ super
20
+ end
21
+
22
+ def self.parse(connection, response)
23
+ # Parse data from response
24
+ if response.is_json?
25
+ user = User.from_json(response)
26
+ else
27
+ user = User.from_xml(response)
28
+ end
29
+ # Store connection in object for future use
30
+ user.connection = connection
31
+ # Done
32
+ return user
33
+ end
34
+
35
+ def self.from_json(json)
36
+ # Read JSON
37
+ doc = JSON.parse(json)
38
+ data = {}
39
+ data[:environment_uid] = doc['user']['environment']['uid']
40
+ data[:uid] = doc['user']['uid']
41
+ data[:created] = DateTime.parse(doc['user']['created'])
42
+ data[:modified] = DateTime.parse(doc['user']['modified'])
43
+ data[:username] = doc['user']['username']
44
+ data[:name] = doc['user']['name']
45
+ data[:email] = doc['user']['email']
46
+ data[:api_version] = doc['user']['apiVersion']
47
+ data[:status] = doc['user']['status']
48
+ # Create object
49
+ User.new(data)
50
+ rescue
51
+ raise AMEE::BadData.new("Couldn't load User from JSON. Check that your URL is correct.\n#{json}")
52
+ end
53
+
54
+ def self.from_xml(xml)
55
+ # Parse data from response into hash
56
+ doc = REXML::Document.new(xml)
57
+ data = {}
58
+ data[:environment_uid] = REXML::XPath.first(doc, "//Environment/@uid").to_s
59
+ data[:uid] = REXML::XPath.first(doc, "//User/@uid").to_s
60
+ data[:created] = DateTime.parse(REXML::XPath.first(doc, "//User/@created").to_s)
61
+ data[:modified] = DateTime.parse(REXML::XPath.first(doc, "//User/@modified").to_s)
62
+ data[:username] = REXML::XPath.first(doc, "//User/Username").text
63
+ data[:name] = REXML::XPath.first(doc, "//User/Name").text
64
+ data[:email] = REXML::XPath.first(doc, "//User/Email").text
65
+ data[:api_version] = REXML::XPath.first(doc, "//User/ApiVersion").text
66
+ data[:status] = REXML::XPath.first(doc, "//User/Status").text
67
+ # Create object
68
+ User.new(data)
69
+ rescue
70
+ raise AMEE::BadData.new("Couldn't load User from XML. Check that your URL is correct.\n#{xml}")
71
+ end
72
+
73
+ def self.get(connection, path, options = {})
74
+ # Load data from path
75
+ response = connection.get(path, options).body
76
+ # Parse response
77
+ User.parse(connection, response)
78
+ rescue
79
+ raise AMEE::BadData.new("Couldn't load User. Check that your URL is correct.\n#{response}")
80
+ end
81
+
82
+ def update(options = {})
83
+ connection.put(full_path, options).body
84
+ AMEE::Admin::User.get(connection, full_path)
85
+ end
86
+
87
+ def self.create(connection, environment_uid, options = {})
88
+ unless options.is_a?(Hash)
89
+ raise AMEE::ArgumentError.new("Second argument must be a hash of options!")
90
+ end
91
+ # Send data
92
+ response = connection.post("/environments/#{environment_uid}/users", options).body
93
+ # Parse response
94
+ User.parse(connection, response)
95
+ rescue
96
+ raise AMEE::BadData.new("Couldn't create User. Check that your information is correct.\n#{response}")
97
+ end
98
+
99
+ def delete
100
+ connection.delete(full_path)
101
+ rescue
102
+ raise AMEE::BadData.new("Couldn't delete User. Check that your information is correct.")
103
+ end
104
+
105
+ def full_path
106
+ "/environments/#{@environment_uid}/users/#{uid}"
107
+ end
108
+
109
+ end
110
+ end
111
+ end
data/rails/init.rb CHANGED
@@ -8,17 +8,6 @@ if File.exist?(amee_config)
8
8
  $AMEE_CONFIG = YAML.load_file(amee_config)[RAILS_ENV]
9
9
  # Create a global AMEE connection that we can use from anywhere in this app
10
10
  AMEE::Rails.establish_connection($AMEE_CONFIG['server'], $AMEE_CONFIG['username'], $AMEE_CONFIG['password'])
11
- else
12
- # Create an example AMEE config file and save it to config/amee.yml
13
- example_config = {}
14
- example_config['development'] = {'server' => "stage.co2.dgen.net", 'username' => "your_amee_username", 'password' => "your_amee_password"}
15
- example_config['production'] = {'server' => "stage.co2.dgen.net", 'username' => "your_amee_username", 'password' => "your_amee_password"}
16
- example_config['test'] = {'server' => "stage.co2.dgen.net", 'username' => "your_amee_username", 'password' => "your_amee_password"}
17
- File.open(amee_config, 'w') do |out|
18
- YAML.dump(example_config, out)
19
- end
20
- # Inform the user that we've written a file for them
21
- raise AMEE::ConnectionFailed.new("config/amee.yml doesn't exist. I've created one for you - please add your API keys to it.")
22
11
  end
23
12
 
24
13
  # Add AMEE extensions into ActiveRecord::Base
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Floppy-amee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.22
4
+ version: 2.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Smith
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-06 00:00:00 -07:00
12
+ date: 2009-09-15 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -62,6 +62,7 @@ files:
62
62
  - lib/amee/rails.rb
63
63
  - lib/amee/pager.rb
64
64
  - lib/amee/item_definition.rb
65
+ - lib/amee/user.rb
65
66
  - bin/ameesh
66
67
  - examples/list_profiles.rb
67
68
  - examples/create_profile.rb
@@ -70,6 +71,7 @@ files:
70
71
  - examples/view_data_item.rb
71
72
  - init.rb
72
73
  - rails/init.rb
74
+ - amee.example.yml
73
75
  has_rdoc: true
74
76
  homepage: http://github.com/Floppy/amee-ruby
75
77
  licenses: