amee 2.0.35 → 2.2.0

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/CHANGELOG ADDED
@@ -0,0 +1,11 @@
1
+ = Changelog
2
+
3
+ == 2.2.0
4
+
5
+ * Add SSL support. SSL connections are now used by default.
6
+ * Log4r support
7
+ * Support for reading ItemValueDefinitions
8
+ * Include accessors from other objects
9
+ * Internal improvements including
10
+ * Improved paging support
11
+ * Tidier code for collections
data/README CHANGED
@@ -12,13 +12,15 @@ Documentation: http://docs.github.com/Floppy/amee-ruby
12
12
 
13
13
  == INSTALLATION
14
14
 
15
- 1) Enable gems from gemcutter, if you haven't already done so:
16
- > sudo gem install gemcutter
17
- > sudo gem tumble
18
-
19
- 2) Install gem
15
+ 1) Install gem
20
16
  > sudo gem install amee
21
17
 
18
+ == IMPORTANT CHANGES when upgrading to 2.2.0 and above
19
+
20
+ SSL connections are now supported, and are used BY DEFAULT.If you do not want to
21
+ use SSL, you can disable it using the ":ssl => false" option to Connection.new, or
22
+ by adding "ssl: false" to your amee.yml if you are using Rails.
23
+
22
24
  == IMPORTANT CHANGES when upgrading beyond 2.0.25
23
25
 
24
26
  If you are using the $amee connection in your Rails apps, this is now deprecated
@@ -60,7 +62,7 @@ This gem can also be used as a Rails plugin. You can either extract it into
60
62
  vendor/plugins, or use the new-style config.gem command in environment.rb. For
61
63
  example:
62
64
 
63
- config.gem "amee", :version => '>= 2.0.26'
65
+ config.gem "amee", :version => '~> 2.2.0'
64
66
 
65
67
  If you copy amee.example.yml from the gem source directory to amee.yml in your
66
68
  app's config directory, a persistent AMEE connection will be available from
data/amee.example.yml CHANGED
@@ -2,11 +2,14 @@ development:
2
2
  server: stage.amee.com
3
3
  username: your_amee_username
4
4
  password: your_amee_password
5
+ #ssl: false # Uncomment if you don't want to use SSL
5
6
  test:
6
7
  server: stage.amee.com
7
8
  username: your_amee_username
8
9
  password: your_amee_password
10
+ #ssl: false # Uncomment if you don't want to use SSL
9
11
  production:
10
12
  server: live.amee.com
11
13
  username: your_amee_username
12
14
  password: your_amee_password
15
+ #ssl: false # Uncomment if you don't want to use SSL
data/cacert.pem ADDED
@@ -0,0 +1,45 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUF
3
+ ADCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0
4
+ IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEw
5
+ HwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVU
6
+ Ti1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5
7
+ MTgxOTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQH
8
+ Ew5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3
9
+ b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNV
10
+ BAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3DQEBAQUA
11
+ A4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZ
12
+ FvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6N
13
+ q9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEH
14
+ OG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNdoI6yqqr2jmmI
15
+ BsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjfPe58
16
+ BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhb
17
+ AgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
18
+ VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWG
19
+ M2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3
20
+ YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
21
+ BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0o
22
+ XnWO6y1n7k57K9cM//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjA
23
+ bPLPSbtNk28GpgoiskliCE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59
24
+ Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4f
25
+ Fm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchq
26
+ J/kniCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0q
27
+ UZ6B+dQ7XnASfxAynB67nfhmqA==
28
+ -----END CERTIFICATE-----
29
+ -----BEGIN CERTIFICATE-----
30
+ MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJV
31
+ UzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1
32
+ aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0
33
+ MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoT
34
+ E0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJl
35
+ IEdsb2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
36
+ gYkCgYEAuucXkAJlsTRVPEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQy
37
+ td4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORR
38
+ OhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxnhcXIw2EC
39
+ AwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8w
40
+ HwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6o
41
+ oHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf
42
+ 2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkAZ70Br83gcfxa
43
+ z2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIYNMR1
44
+ pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
45
+ -----END CERTIFICATE-----
data/lib/amee.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rexml/document'
2
2
  require 'active_support'
3
+ require 'log4r'
3
4
 
4
5
  # We don't NEED the JSON gem, but if it's available, use it.
5
6
  begin
@@ -26,9 +27,12 @@ class String
26
27
  end
27
28
  end
28
29
 
30
+ require 'amee/logger'
29
31
  require 'amee/version'
30
32
  require 'amee/exceptions'
31
33
  require 'amee/connection'
34
+ require 'amee/parse_helper'
35
+ require 'amee/collection'
32
36
  require 'amee/object'
33
37
  require 'amee/data_object'
34
38
  require 'amee/profile_object'
@@ -43,6 +47,7 @@ require 'amee/profile_item_value'
43
47
  require 'amee/drill_down'
44
48
  require 'amee/pager'
45
49
  require 'amee/item_definition'
50
+ require 'amee/item_value_definition'
46
51
  require 'amee/user'
47
52
 
48
53
  class Date
@@ -0,0 +1,64 @@
1
+ module AMEE
2
+ class Collection < Array
3
+ include ParseHelper
4
+ attr_reader :pager,:connection,:doc,:json,:response
5
+ def initialize(connection, options = {})
6
+ # Load data from path
7
+ @options=options
8
+ @max=options.delete :resultMax
9
+ @connection=connection
10
+ # Parse data from response
11
+ each_page do
12
+ parse_page
13
+ end
14
+ rescue => err
15
+ #raise AMEE::BadData.new("Couldn't load #{self.class.name}.\n#{response} due to #{err}")
16
+ raise AMEE::BadData.new("Couldn't load #{self.class.name}.\n#{response}")
17
+ end
18
+ def parse_page
19
+ if json
20
+ jsoncollector.each do |p|
21
+ obj = klass.new(parse_json(p))
22
+ obj.connection = connection
23
+ self << obj
24
+ break if @max&&length>=@max
25
+ end
26
+ else
27
+ REXML::XPath.first(doc,xmlcollectorpath.split('/')[1...-1].join('/')) or
28
+ raise AMEE::BadData.new("Couldn't load #{self.class.name}.\n#{response}")
29
+ REXML::XPath.each(doc, xmlcollectorpath) do |p|
30
+ obj=klass.new(parse_xml(p))
31
+ obj.connection = connection
32
+ self << obj
33
+ break if @max&&length>=@max
34
+ end
35
+ end
36
+ end
37
+
38
+ def fetch
39
+ @options.merge! @pager.options if @pager
40
+ @response= @connection.get(collectionpath, @options).body
41
+ if @response.is_json?
42
+ @json = true
43
+ @doc = JSON.parse(@response)
44
+ else
45
+ @doc = REXML::Document.new(@response)
46
+ end
47
+ end
48
+
49
+ def each_page
50
+ begin
51
+ fetch
52
+ yield
53
+ if json
54
+ @pager = AMEE::Pager.from_json(doc['pager'])
55
+ else
56
+ @pager = AMEE::Pager.from_xml(REXML::XPath.first(doc, '/Resources//Pager'))
57
+ end
58
+ break if @max && length>=@max
59
+ end while @pager && @pager.next! #pager is nil if no pager in response,
60
+ # pager.next! is false if @pager said current=last.
61
+ end
62
+ end
63
+ end
64
+
@@ -1,8 +1,11 @@
1
1
  require 'net/http'
2
+ require 'net/https'
2
3
 
3
4
  module AMEE
4
5
  class Connection
5
6
 
7
+ RootCA = File.dirname(__FILE__) + '/../../cacert.pem'
8
+
6
9
  def initialize(server, username, password, options = {})
7
10
  unless options.is_a?(Hash)
8
11
  raise AMEE::ArgumentError.new("Fourth argument must be a hash of options!")
@@ -10,8 +13,11 @@ module AMEE
10
13
  @server = server
11
14
  @username = username
12
15
  @password = password
16
+ @ssl = (options[:ssl] == false) ? false : true
17
+ @port = @ssl ? 443 : 80
13
18
  @auth_token = nil
14
19
  @format = options[:format] || (defined?(JSON) ? :json : :xml)
20
+ @amee_source = options[:amee_source]
15
21
  if !valid?
16
22
  raise "You must supply connection details - server, username and password are all required!"
17
23
  end
@@ -20,20 +26,29 @@ module AMEE
20
26
  $cache ||= {}
21
27
  end
22
28
  # Make connection to server
23
- @http = Net::HTTP.new(@server)
29
+ @http = Net::HTTP.new(@server, @port)
30
+ if @ssl == true
31
+ @http.use_ssl = true
32
+ if File.exists? RootCA
33
+ @http.ca_file = RootCA
34
+ @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
35
+ @http.verify_depth = 5
36
+ end
37
+ end
24
38
  @http.read_timeout = 60
25
39
  @http.set_debug_output($stdout) if options[:enable_debug]
40
+ @debug = options[:enable_debug]
26
41
  end
27
42
 
28
43
  attr_reader :format
29
44
  attr_reader :server
30
45
  attr_reader :username
31
46
  attr_reader :password
32
-
47
+
33
48
  def timeout
34
49
  @http.read_timeout
35
50
  end
36
-
51
+
37
52
  def timeout=(t)
38
53
  @http.read_timeout = t
39
54
  end
@@ -46,7 +61,7 @@ module AMEE
46
61
  def valid?
47
62
  @username && @password && @server
48
63
  end
49
-
64
+
50
65
  def authenticated?
51
66
  !@auth_token.nil?
52
67
  end
@@ -68,7 +83,7 @@ module AMEE
68
83
  $cache[path] = response if @enable_caching
69
84
  return response
70
85
  end
71
-
86
+
72
87
  def post(path, data = {})
73
88
  # Allow format override
74
89
  format = data.delete(:format) || @format
@@ -140,6 +155,7 @@ module AMEE
140
155
  post = Net::HTTP::Post.new("/auth/signIn")
141
156
  post.body = "username=#{@username}&password=#{@password}"
142
157
  post['Accept'] = content_type(:xml)
158
+ post['X-AMEE-Source'] = @amee_source if @amee_source
143
159
  response = @http.request(post)
144
160
  @auth_token = response['authToken']
145
161
  unless authenticated?
@@ -167,7 +183,7 @@ module AMEE
167
183
  return 'application/atom+xml'
168
184
  end
169
185
  end
170
-
186
+
171
187
  def redirect?(response)
172
188
  response.code == '301' || response.code == '302'
173
189
  end
@@ -176,6 +192,8 @@ module AMEE
176
192
  case response.code
177
193
  when '200', '201'
178
194
  return true
195
+ when '404'
196
+ raise AMEE::NotFound.new("The URL was not found on the server.\nRequest: #{request.method} #{request.path}")
179
197
  when '403'
180
198
  raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}")
181
199
  when '401'
@@ -197,6 +215,7 @@ module AMEE
197
215
  @http.start
198
216
  # Do request
199
217
  begin
218
+ Logger.log.debug("Requesting #{request.class} at #{request.path} with #{request.body} in format #{format}")
200
219
  response = send_request(request, format)
201
220
  end while !response_ok?(response, request)
202
221
  # Return response
@@ -207,19 +226,17 @@ module AMEE
207
226
  # Close HTTP connection
208
227
  @http.finish if @http.started?
209
228
  end
210
-
229
+
211
230
  def send_request(request, format = @format)
212
231
  # Set auth token in cookie (and header just in case someone's stripping cookies)
213
232
  request['Cookie'] = "authToken=#{@auth_token}"
214
233
  request['authToken'] = @auth_token
215
234
  # Set accept header
216
235
  request['Accept'] = content_type(format)
236
+ # Set AMEE source header if set
237
+ request['X-AMEE-Source'] = @amee_source if @amee_source
217
238
  # Do the business
218
239
  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
240
  # Done
224
241
  response
225
242
  end
@@ -17,6 +17,11 @@ module AMEE
17
17
  attr_reader :pager
18
18
  attr_reader :itemdef
19
19
 
20
+ def item_definition
21
+ return nil unless itemdef
22
+ @item_definition ||= AMEE::Admin::ItemDefinition.load(connection,itemdef)
23
+ end
24
+
20
25
  def self.from_json(json)
21
26
  # Parse json
22
27
  doc = JSON.parse(json)
@@ -52,12 +57,15 @@ module AMEE
52
57
  rescue
53
58
  raise AMEE::BadData.new("Couldn't load DataCategory from JSON data. Check that your URL is correct.\n#{json}")
54
59
  end
55
-
60
+
61
+ def self.xmlpathpreamble
62
+ "/Resources/DataCategoryResource/DataCategory/"
63
+ end
56
64
  def self.from_xml(xml)
57
65
  # Parse XML
58
- doc = REXML::Document.new(xml)
66
+ @doc = doc= REXML::Document.new(xml)
59
67
  data = {}
60
- data[:uid] = REXML::XPath.first(doc, "/Resources/DataCategoryResource/DataCategory/@uid").to_s
68
+ data[:uid] = x '@uid'
61
69
  data[:created] = DateTime.parse(REXML::XPath.first(doc, "/Resources/DataCategoryResource/DataCategory/@created").to_s)
62
70
  data[:modified] = DateTime.parse(REXML::XPath.first(doc, "/Resources/DataCategoryResource/DataCategory/@modified").to_s)
63
71
  data[:name] = REXML::XPath.first(doc, '/Resources/DataCategoryResource/DataCategory/?ame').text
@@ -90,7 +98,7 @@ module AMEE
90
98
  rescue
91
99
  raise AMEE::BadData.new("Couldn't load DataCategory from XML data. Check that your URL is correct.\n#{xml}")
92
100
  end
93
-
101
+
94
102
  def self.get(connection, path, orig_options = {})
95
103
  unless orig_options.is_a?(Hash)
96
104
  raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
@@ -119,11 +127,11 @@ module AMEE
119
127
  rescue
120
128
  raise AMEE::BadData.new("Couldn't load DataCategory. Check that your URL is correct.\n#{response}")
121
129
  end
122
-
130
+
123
131
  def self.root(connection)
124
132
  self.get(connection, '/data')
125
133
  end
126
-
134
+
127
135
  def child(child_path)
128
136
  AMEE::Data::Category.get(connection, "#{full_path}/#{child_path}")
129
137
  end
@@ -148,7 +156,7 @@ module AMEE
148
156
 
149
157
  connection = category.connection
150
158
  path = category.full_path
151
-
159
+
152
160
  # Do we want to automatically fetch the item afterwards?
153
161
  get_item = options.delete(:get_item)
154
162
 
@@ -162,7 +170,7 @@ module AMEE
162
170
  options[:newObjectType] = "DC"
163
171
  response = connection.post(path, options)
164
172
  if response['Location']
165
- location = response['Location'].match("http://.*?(/.*)")[1]
173
+ location = response['Location'].match("https??://.*?(/.*)")[1]
166
174
  else
167
175
  category = Category.parse(connection, response.body)
168
176
  location = category.full_path
@@ -200,7 +208,7 @@ module AMEE
200
208
  rescue
201
209
  raise AMEE::BadData.new("Couldn't update Data Category. Check that your information is correct.")
202
210
  end
203
-
211
+
204
212
  end
205
213
  end
206
214
  end
@@ -8,21 +8,29 @@ module AMEE
8
8
  @values = data[:values]
9
9
  @choices = data[:choices]
10
10
  @label = data[:label]
11
- @item_definition = data[:item_definition]
11
+ @item_definition_uid = data[:item_definition]
12
12
  @total_amount = data[:total_amount]
13
13
  @total_amount_unit = data[:total_amount_unit]
14
14
  @start_date = data[:start_date]
15
+ @category_uid = data[:category_uid]
15
16
  super
16
17
  end
17
18
 
18
19
  attr_reader :values
19
20
  attr_reader :choices
20
21
  attr_reader :label
21
- attr_reader :item_definition
22
22
  attr_reader :total_amount
23
23
  attr_reader :total_amount_unit
24
24
  attr_reader :start_date
25
-
25
+ attr_reader :category_uid
26
+ attr_reader :item_definition_uid
27
+
28
+ def item_definition
29
+ return nil unless item_definition_uid
30
+ @item_definition ||= AMEE::Admin::ItemDefinition.load(connection,item_definition_uid)
31
+ end
32
+
33
+
26
34
  def self.from_json(json)
27
35
  # Read JSON
28
36
  doc = JSON.parse(json)
@@ -34,6 +42,7 @@ module AMEE
34
42
  data[:path] = doc['path']
35
43
  data[:label] = doc['dataItem']['label']
36
44
  data[:item_definition] = doc['dataItem']['itemDefinition']['uid']
45
+ data[:category_uid] = doc['dataItem']['dataCategory']['uid']
37
46
  # Read v2 total
38
47
  data[:total_amount] = doc['amount']['value'] rescue nil
39
48
  data[:total_amount_unit] = doc['amount']['unit'] rescue nil
@@ -67,7 +76,7 @@ module AMEE
67
76
  rescue
68
77
  raise AMEE::BadData.new("Couldn't load DataItem from JSON. Check that your URL is correct.\n#{json}")
69
78
  end
70
-
79
+
71
80
  def self.from_xml(xml)
72
81
  # Parse data from response into hash
73
82
  doc = REXML::Document.new(xml)
@@ -79,6 +88,7 @@ module AMEE
79
88
  data[:path] = (REXML::XPath.first(doc, '/Resources/DataItemResource/Path') || REXML::XPath.first(doc, '/Resources/DataItemResource/DataItem/path')).text
80
89
  data[:label] = (REXML::XPath.first(doc, '/Resources/DataItemResource/DataItem/Label') || REXML::XPath.first(doc, '/Resources/DataItemResource/DataItem/label')).text
81
90
  data[:item_definition] = REXML::XPath.first(doc, '/Resources/DataItemResource/DataItem/ItemDefinition/@uid').to_s
91
+ data[:category_uid] = REXML::XPath.first(doc, '/Resources/DataItemResource/DataItem/DataCategory/@uid').to_s
82
92
  # Read v2 total
83
93
  data[:total_amount] = REXML::XPath.first(doc, '/Resources/DataItemResource/Amount').text.to_f rescue nil
84
94
  data[:total_amount_unit] = REXML::XPath.first(doc, '/Resources/DataItemResource/Amount/@unit').to_s rescue nil
@@ -113,7 +123,7 @@ module AMEE
113
123
  raise AMEE::BadData.new("Couldn't load DataItem from XML. Check that your URL is correct.\n#{xml}")
114
124
  end
115
125
 
116
-
126
+
117
127
  def self.get(connection, path, options = {})
118
128
  # Load data from path
119
129
  response = connection.get(path, options).body
@@ -171,7 +181,7 @@ module AMEE
171
181
  # Send data to path
172
182
  response = connection.post(path, options)
173
183
  if response['Location']
174
- location = response['Location'].match("http://.*?(/.*)")[1]
184
+ location = response['Location'].match("https??://.*?(/.*)")[1]
175
185
  else
176
186
  category = Category.parse(connection, response.body)
177
187
  location = category.full_path + "/" + category.items[0][:path]
@@ -203,7 +213,7 @@ module AMEE
203
213
  rescue
204
214
  raise AMEE::BadData.new("Couldn't update DataItem. Check that your information is correct.\n#{response}")
205
215
  end
206
-
216
+
207
217
  def update(options = {})
208
218
  AMEE::Data::Item.update(connection, full_path, options)
209
219
  end
@@ -213,7 +223,7 @@ module AMEE
213
223
  rescue
214
224
  raise AMEE::BadData.new("Couldn't delete DataItem. Check that your information is correct.")
215
225
  end
216
-
226
+
217
227
  def value(name_or_path_or_uid)
218
228
  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}
219
229
  val ? val[:value] : nil