ALD 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/lib/ALD/api.rb +285 -0
- data/lib/ALD/collection.rb +96 -0
- data/lib/ALD/collection_entry.rb +77 -0
- data/lib/ALD/conditioned.rb +216 -0
- data/lib/ALD/item.rb +186 -0
- data/lib/ALD/item_collection.rb +169 -0
- data/lib/ALD/local_filter.rb +136 -0
- data/lib/ALD/user.rb +94 -0
- data/lib/ALD/user_collection.rb +140 -0
- metadata +12 -4
- data/lib/ALD/schema.xsd +0 -340
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'semantic'
|
2
|
+
|
3
|
+
module ALD
|
4
|
+
class API
|
5
|
+
# Internal: used by Collection classes to work with special conditions in #where.
|
6
|
+
#
|
7
|
+
# Requires @conditions to be the instance's condition Hash.
|
8
|
+
module Conditioned
|
9
|
+
# Public: Filter the Collection's data.
|
10
|
+
# See the documentation on the individual classes for more information.
|
11
|
+
def where(conditions)
|
12
|
+
return self if conditions.nil? || conditions.empty?
|
13
|
+
new_conditions = merge_conditions(conditions)
|
14
|
+
|
15
|
+
if initialized? && Collection::LocalFilter.can_apply?(conditions, self.class::LOCAL_CONDITIONS)
|
16
|
+
self.class::new(
|
17
|
+
@api,
|
18
|
+
new_conditions,
|
19
|
+
Collection::LocalFilter.apply_conditions(@data, conditions)
|
20
|
+
)
|
21
|
+
else
|
22
|
+
self.class::new(@api, new_conditions)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Internal: The HTTP query conditions for the range specified in the
|
29
|
+
# instance's conditions.
|
30
|
+
#
|
31
|
+
# Returns a Hash, that contains the query parameters matching the range
|
32
|
+
# specified in the conditions, or an empty Hash if there is no range
|
33
|
+
# specified.
|
34
|
+
def range_query
|
35
|
+
data = {}
|
36
|
+
if @conditions.key?(:range)
|
37
|
+
data['start'] = @conditions[:range].min
|
38
|
+
data['count'] = @conditions[:range].max - @conditions[:range].min + 1
|
39
|
+
end
|
40
|
+
data
|
41
|
+
end
|
42
|
+
|
43
|
+
# Internal: The HTTP query conditions for the sorting specified in the
|
44
|
+
# instance's conditions.
|
45
|
+
#
|
46
|
+
# Returns a Hash containing the query parameters matching the specified
|
47
|
+
# sorting, or an empty Hash if there's no sorting specified.
|
48
|
+
def sort_query
|
49
|
+
Hash[
|
50
|
+
present_conditions(%w[sort]).map { |cond| [cond, @conditions[cond.to_sym].map { |k, dir| "#{dir == :desc ? '-' : ''}#{k}" }.join(',')] }
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Internal: The HTTP query conditions for exact queries for a set of
|
55
|
+
# given conditions.
|
56
|
+
#
|
57
|
+
# conds - an Array of Strings, containing the condition names to handle
|
58
|
+
#
|
59
|
+
# Returns a Hash with the query parameters matching the instance's values
|
60
|
+
# on the specified conditions, or an empty Hash, if there are none.
|
61
|
+
def exact_queries(conds)
|
62
|
+
Hash[
|
63
|
+
present_conditions(conds).map { |cond| [cond, @conditions[cond.to_sym]] }
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Internal: The HTTP query conditions for queries for an array of values
|
68
|
+
# for the given conditions.
|
69
|
+
#
|
70
|
+
# conds - an Array of Strings, containing the condition names to handle
|
71
|
+
#
|
72
|
+
# Returns a Hash with the query parameters matching the instance's values
|
73
|
+
# on the specified conditions, or an empty Hash.
|
74
|
+
def array_queries(conds)
|
75
|
+
Hash[
|
76
|
+
present_conditions(conds).map { |cond| [cond, @conditions[cond.to_sym].join(',')] }
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
# Internal: The HTTP query conditions for queries with conditions that
|
81
|
+
# can be switched on, off or indeterminate.
|
82
|
+
#
|
83
|
+
# conds - an Array of Strings, containing the condition names to handle
|
84
|
+
#
|
85
|
+
# Returns a Hash with the query parameters matching the instance's values
|
86
|
+
# on the specified conditions, or an empty Hash.
|
87
|
+
def switch_queries(conds)
|
88
|
+
map = {true => 'true', false => 'false', nil => 'both'}
|
89
|
+
Hash[
|
90
|
+
present_conditions(conds).map { |cond| [cond, map[@conditions[cond.to_sym]]] }
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Internal: The HTTP query conditions for queries with conditions that
|
95
|
+
# allow specifying a range of values.
|
96
|
+
#
|
97
|
+
# conds - an Array of Strings, containing the condition names to handle
|
98
|
+
#
|
99
|
+
# Returns a Hash with the query parameters matching the instance's values
|
100
|
+
# on the specified conditions, or an empty Hash.
|
101
|
+
def range_condition_queries(conds)
|
102
|
+
Hash[
|
103
|
+
present_conditions(conds).map { |cond|
|
104
|
+
fields = @conditions[cond.to_sym].is_a?(Array) ? @conditions[cond.to_sym] : [@conditions[cond.to_sym]]
|
105
|
+
fields.map do |field|
|
106
|
+
match = RANGE_REGEX.match(field)
|
107
|
+
if match.nil? # just a specific field
|
108
|
+
[cond, field]
|
109
|
+
else # min or max
|
110
|
+
["#{cond}-#{match[1] == '>=' ? 'min' : 'max'}", match[2]]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
}.flatten(1)
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Internal: Get the subset of conditions that are present on the instance
|
118
|
+
#
|
119
|
+
# conds - an Array of Strings, containing the condition names to check
|
120
|
+
#
|
121
|
+
# Returns an Array of Strings with a subset of the given conds, namely
|
122
|
+
# those that are present on @conditions.
|
123
|
+
def present_conditions(conds)
|
124
|
+
conds.select { |cond| @conditions.key?(cond.to_sym) }
|
125
|
+
end
|
126
|
+
|
127
|
+
# Internal: Merge new conditions with the current ones.
|
128
|
+
#
|
129
|
+
# conditions - the new condition Hash to merge
|
130
|
+
#
|
131
|
+
# Returns the merged Hash
|
132
|
+
#
|
133
|
+
# Raises ArgumentError if the conditions are incompatible
|
134
|
+
def merge_conditions(conditions)
|
135
|
+
@conditions.merge(conditions) do |key, old_value, new_value|
|
136
|
+
if self.class::RANGE_CONDITIONS.include?(key.to_s)
|
137
|
+
merge_ranges(key, old_value, new_value) # handle merging for cases like 'downloads >= 5' and 'downloads <= 9' etc.
|
138
|
+
elsif self.class::ARRAY_CONDITIONS.include?(key.to_s)
|
139
|
+
old_value + new_value
|
140
|
+
elsif key == :range # not a "range condition" in the sense used above
|
141
|
+
range_offset(new_value)
|
142
|
+
elsif key == :sort
|
143
|
+
new_value # enable re-sorting
|
144
|
+
else
|
145
|
+
raise ArgumentError # for other overwrites fail!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Internal: A regex to determine if a range condition is specifying a range.
|
151
|
+
RANGE_REGEX = /^\s*(<\=|>\=)\s*(.*)$/
|
152
|
+
|
153
|
+
# Internal: Handle condition conflicts for range conditions. Used by #where.
|
154
|
+
#
|
155
|
+
# key - the Symbol key whose range is merged
|
156
|
+
# old - the old range condition value
|
157
|
+
# new - the new range condition value to be applied on top of the old one
|
158
|
+
#
|
159
|
+
# Returns the value that should be used in the merged conditions.
|
160
|
+
#
|
161
|
+
# Raises ArgumentError if the conflict cannot be resolved.
|
162
|
+
def merge_ranges(key, old, new)
|
163
|
+
constraints = [new, old]
|
164
|
+
data = constraints.map do |c|
|
165
|
+
match = RANGE_REGEX.match(c)
|
166
|
+
if match.nil?
|
167
|
+
[nil, c]
|
168
|
+
elsif key == :version
|
169
|
+
[match[1], Semantic::Version.new(match[2])]
|
170
|
+
else
|
171
|
+
[match[1], match[2]]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
ops, values = data.map(&:first), data.map(&:last)
|
175
|
+
|
176
|
+
if ops[0] != ops[1] # one min, one max OR one min/max, one exact
|
177
|
+
constraints # => keep both
|
178
|
+
|
179
|
+
elsif ops.none?(&:'nil?') # two range constraints of same type
|
180
|
+
ops[0] == '>=' ? ">= #{values.max.to_s}" : "<= #{values.min.to_s}"
|
181
|
+
|
182
|
+
else # two exact values
|
183
|
+
if constraints[0].strip == constraints[1].strip # if both are the same, just keep one
|
184
|
+
constraints[0]
|
185
|
+
else # otherwise this can't be good - throw an error
|
186
|
+
raise ArgumentError
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Internal: Compute an absolute Range from a given relative Range. As
|
192
|
+
# ranges specified in #where are relative to this collection, they must
|
193
|
+
# be transformed to absolute ranges before being passed to ::new.
|
194
|
+
#
|
195
|
+
# new_range - the relative Range to transform
|
196
|
+
#
|
197
|
+
# Returns the absolute Range.
|
198
|
+
#
|
199
|
+
# Raises ArgumentError if the relative Range does not fit into this
|
200
|
+
# collection's Range.
|
201
|
+
def range_offset(new_range)
|
202
|
+
if @conditions[:range].nil?
|
203
|
+
min, max = 0, Float::Infinity
|
204
|
+
else
|
205
|
+
min, max = @conditions[:range].min, @conditions[:range].max
|
206
|
+
end
|
207
|
+
|
208
|
+
new_min = min + new_range.min
|
209
|
+
new_max = new_min + new_range.max - new_range.min # == new_min + new_range.size - 1
|
210
|
+
raise ArgumentError if new_min > max || new_max > max
|
211
|
+
|
212
|
+
(new_min..new_max)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
data/lib/ALD/item.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require_relative 'collection_entry'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module ALD
|
5
|
+
class API
|
6
|
+
# Public: An item (e.g. a library or app) uploaded to an ALD server.
|
7
|
+
class Item < CollectionEntry
|
8
|
+
|
9
|
+
# Public: Get the ID of the item.
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
#
|
13
|
+
# puts item.id
|
14
|
+
#
|
15
|
+
# Returns a String of 32 characters, containing the item's GUID.
|
16
|
+
#
|
17
|
+
# Signature
|
18
|
+
#
|
19
|
+
# item()
|
20
|
+
|
21
|
+
# Public: Get the name of the item.
|
22
|
+
#
|
23
|
+
# Examples
|
24
|
+
#
|
25
|
+
# puts "Item: #{item.name}"
|
26
|
+
#
|
27
|
+
# Returns a String containing the item name.
|
28
|
+
#
|
29
|
+
# Signature
|
30
|
+
#
|
31
|
+
# name()
|
32
|
+
|
33
|
+
# Public: Get the item version.
|
34
|
+
#
|
35
|
+
# Examples
|
36
|
+
#
|
37
|
+
# puts "#{item.name} v#{item.version}"
|
38
|
+
#
|
39
|
+
# Returns a String containing the version of the item.
|
40
|
+
#
|
41
|
+
# Signature
|
42
|
+
#
|
43
|
+
# version()
|
44
|
+
|
45
|
+
# Public: Get the item's summary text. This method might trigger a HTTP
|
46
|
+
# request.
|
47
|
+
#
|
48
|
+
# Returns a String summarizing the item's purpose and contents.
|
49
|
+
#
|
50
|
+
# Signature
|
51
|
+
#
|
52
|
+
# summary()
|
53
|
+
|
54
|
+
# Public: Get the item's description text. This method might trigger a
|
55
|
+
# HTTP request.
|
56
|
+
#
|
57
|
+
# Returns a String with the item's description.
|
58
|
+
#
|
59
|
+
# Signature
|
60
|
+
#
|
61
|
+
# description()
|
62
|
+
|
63
|
+
# Public: Get the time the item was uploaded. This method might trigger a
|
64
|
+
# HTTP request.
|
65
|
+
#
|
66
|
+
# Returns a DateTime describing the time the item was first uploaded to
|
67
|
+
# the ALD server.
|
68
|
+
#
|
69
|
+
# Signature
|
70
|
+
#
|
71
|
+
# uploaded()
|
72
|
+
|
73
|
+
# Public: Get if the item has been marked as reviewed by the ALD server.
|
74
|
+
# This method might trigger a HTTP request.
|
75
|
+
#
|
76
|
+
# Returns a Boolean indicating if the item was revieed or not.
|
77
|
+
#
|
78
|
+
# Signature
|
79
|
+
#
|
80
|
+
# reviewed()
|
81
|
+
|
82
|
+
# Public: Get the number of downloads for the item. This method might
|
83
|
+
# trigger a HTTP request.
|
84
|
+
#
|
85
|
+
# Returns an Integer indicating how often the item was downloaded.
|
86
|
+
#
|
87
|
+
# Signature
|
88
|
+
#
|
89
|
+
# downloads()
|
90
|
+
|
91
|
+
# Public: Get the tags the item was tagged with. This method might
|
92
|
+
# trigger a HTTP request.
|
93
|
+
#
|
94
|
+
# Returns an Array of Symbols representing the tags.
|
95
|
+
#
|
96
|
+
# Signature
|
97
|
+
#
|
98
|
+
# tags()
|
99
|
+
|
100
|
+
# Public: get author information from the item. This method might trigger
|
101
|
+
# a HTTP request.
|
102
|
+
#
|
103
|
+
# Returns an Array of Hashes describing the authors.
|
104
|
+
#
|
105
|
+
# Signature
|
106
|
+
#
|
107
|
+
# authors()
|
108
|
+
|
109
|
+
# Public: Get the user who owns the item. This method might trigger a
|
110
|
+
# HTTP request.
|
111
|
+
#
|
112
|
+
# Returns the ALD::API::User who owns the item.
|
113
|
+
#
|
114
|
+
# Signature
|
115
|
+
#
|
116
|
+
# user()
|
117
|
+
|
118
|
+
# Public: Get the ratings the item was given. This method might trigger a
|
119
|
+
# HTTP request.
|
120
|
+
#
|
121
|
+
# Returns an Array of Integers representing the ratings given to the item
|
122
|
+
# by users.
|
123
|
+
#
|
124
|
+
# Signature
|
125
|
+
#
|
126
|
+
# ratings()
|
127
|
+
|
128
|
+
# Internal: Create a new instance for given data. This method should not
|
129
|
+
# called by library consumers. Instead access entries via API#item or
|
130
|
+
# ItemCollection#[].
|
131
|
+
#
|
132
|
+
# api - the ALD::API instance this item belongs to
|
133
|
+
# data - a Hash containing data concerning the item:
|
134
|
+
# id - the GUID of the item
|
135
|
+
# name - the name of the item
|
136
|
+
# version - the semver version of the item
|
137
|
+
# The above fields are mandatory. However, the hash may
|
138
|
+
# contain a lot more data about the item.
|
139
|
+
# initialized - a Boolean indicating if data only contains the mandatory
|
140
|
+
# fields or *all* data on the item.
|
141
|
+
def initialize(api, data, initialized = false)
|
142
|
+
raise ArgumentError unless Item.valid_data?(data)
|
143
|
+
super(api, data, initialized)
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# Internal: If the item was initialized with only mandatory data, use the
|
149
|
+
# API to request all missing information.
|
150
|
+
#
|
151
|
+
# Returns nothing.
|
152
|
+
def request
|
153
|
+
@data = @api.request("/items/#{id}")
|
154
|
+
@data['uploaded'] = DateTime.parse(@data['uploaded'])
|
155
|
+
@data['tags'].map!(&:to_sym)
|
156
|
+
@data['user'] = @api.user(@data['user'])
|
157
|
+
end
|
158
|
+
|
159
|
+
# Internal: Ensure a Hash contains all information necessary to be passed
|
160
|
+
# to #new.
|
161
|
+
#
|
162
|
+
# data - the Hash to check for mandatory fields
|
163
|
+
#
|
164
|
+
# Returns true if the Hash is valid, false otherwise.
|
165
|
+
def self.valid_data?(data)
|
166
|
+
data.is_a?(Hash) && initialized_attributes.all? { |k| data.key?(k) }
|
167
|
+
end
|
168
|
+
|
169
|
+
# Internal: Override of CollectionEntry#initialized_attributes to enable
|
170
|
+
# automatic method definition, in this case #id, #name and #version.
|
171
|
+
#
|
172
|
+
# Returns an Array of attribute names (String)
|
173
|
+
def self.initialized_attributes
|
174
|
+
%w[id name version]
|
175
|
+
end
|
176
|
+
|
177
|
+
# Internal: Override of CollectionEntry#requested_attributes to enable
|
178
|
+
# automatic method definition.
|
179
|
+
#
|
180
|
+
# Returns an Array of attribute names (String)
|
181
|
+
def self.requested_attributes
|
182
|
+
%w[summary description uploaded reviewed downloads tags authors user ratings]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require_relative 'collection'
|
2
|
+
require_relative 'conditioned'
|
3
|
+
require_relative 'local_filter'
|
4
|
+
|
5
|
+
module ALD
|
6
|
+
class API
|
7
|
+
# Public: Represents a (possibly filtered) set of items on an ALD server
|
8
|
+
class ItemCollection < Collection
|
9
|
+
include Conditioned
|
10
|
+
|
11
|
+
# Internal: Create a new instance. This should not be called by library
|
12
|
+
# consumers. Instead use API#items or #where to get a new instance.
|
13
|
+
#
|
14
|
+
# api - the ALD::API instance this collection belongs to
|
15
|
+
# conditions - a Hash of conditions items in this collection must meet
|
16
|
+
# data - an Array of Hashes representing the items in this
|
17
|
+
# collection:
|
18
|
+
# id - the GUID of the item
|
19
|
+
# name - the item's name
|
20
|
+
# version - the item's semver version
|
21
|
+
def initialize(api, conditions = {}, data = nil)
|
22
|
+
super(api, conditions, data)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Public: Access an individual item by ID, name and version or index in
|
26
|
+
# the collection. This method may trigger a HTTP request.
|
27
|
+
#
|
28
|
+
# Examples
|
29
|
+
#
|
30
|
+
# items['185d265f24654545aad3f88e8a383339'] # access the item with this ID
|
31
|
+
# items['MyApp', '0.1.2'] # access a specific version of an item
|
32
|
+
# items[4] # access the 5th item in the collection (zero-based index)
|
33
|
+
# # This makes most sense in an explicitly ordered collection
|
34
|
+
#
|
35
|
+
# Returns the corresponding ALD::API::Item instance, or nil if not found
|
36
|
+
#
|
37
|
+
# Signature
|
38
|
+
#
|
39
|
+
# [](id)
|
40
|
+
# [](name, version)
|
41
|
+
# [](index)
|
42
|
+
#
|
43
|
+
# id - a GUID String uniquely identifying the item
|
44
|
+
# name - a String containing the item's name
|
45
|
+
# version - a String containing the item's semver version
|
46
|
+
# index - an Integer with the item's zero-based index within the
|
47
|
+
# collection.
|
48
|
+
|
49
|
+
# Internal: filter conditions that allow specifying a range, like
|
50
|
+
# 'version-min=0.2.1&version-max=3.4.5'
|
51
|
+
RANGE_CONDITIONS = %w[version downloads rating]
|
52
|
+
|
53
|
+
# Internal: filter conditions that allow specifying an array.
|
54
|
+
ARRAY_CONDITIONS = %w[tags]
|
55
|
+
|
56
|
+
# Internal: filter conditions that can be handled locally.
|
57
|
+
LOCAL_CONDITIONS = %w[name version]
|
58
|
+
|
59
|
+
# Public: Filter and/or sort this collection and return a new collection
|
60
|
+
# containing a subset of its items.
|
61
|
+
#
|
62
|
+
# conditions - a Hash of conditions to filter for
|
63
|
+
# :name - filter for items with this name (String)
|
64
|
+
# :user - only return items by this user (given the user
|
65
|
+
# name or the ID) (String)
|
66
|
+
# :type - only return items of this type (String)
|
67
|
+
# :downloads - If given only a number, return only items with
|
68
|
+
# this number of downloads. More commonly, pass
|
69
|
+
# a string like '>= 4' or '<= 5' (or an array of
|
70
|
+
# such strings) to select items in a range of
|
71
|
+
# download counts.
|
72
|
+
# :rating - Select items with a given rating. Like
|
73
|
+
# for :downloads, ranges can be specified.
|
74
|
+
# :version - Only items with a given semver version number.
|
75
|
+
# Here as well, ranges can be specified. Semver
|
76
|
+
# rules are taken into account when sorting.
|
77
|
+
# :stable - Set to true to only return items whose semver
|
78
|
+
# version indicates they're stable.
|
79
|
+
# :reviewed - Set to true to filter for items that are marked
|
80
|
+
# as reviewed by the server.
|
81
|
+
# :tags - A tag or an array of tags to filter for.
|
82
|
+
# :sort - an Array of sorting criteria, in descending
|
83
|
+
# order of precedence; or a Hash where the keys
|
84
|
+
# are the sorting criteria, and the values (:asc,
|
85
|
+
# :desc) indicate sorting order.
|
86
|
+
# :range - A zero-based Range of items to return. This
|
87
|
+
# makes most sense in combination with sorting.
|
88
|
+
# Note that the range is relative to the
|
89
|
+
# collection the operation is performed upon.
|
90
|
+
#
|
91
|
+
# Returns a new ItemCollection instance (or self, if conditions is nil)
|
92
|
+
#
|
93
|
+
# Raises ArgumentError if the conditions are invalid or incompatible with
|
94
|
+
# this collection's conditions.
|
95
|
+
#
|
96
|
+
# Signature
|
97
|
+
#
|
98
|
+
# where(conditions)
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# Internal: Make a HTTP request to the ALD server to get the list of item
|
103
|
+
# hashes matching this collection's conditions.
|
104
|
+
#
|
105
|
+
# Returns nothing.
|
106
|
+
def request
|
107
|
+
data = [
|
108
|
+
exact_queries(%w[name user type]),
|
109
|
+
switch_queries(%w[stable reviewed]),
|
110
|
+
array_queries(%w[tags]),
|
111
|
+
range_condition_queries(%w[downloads rating version]),
|
112
|
+
sort_query,
|
113
|
+
range_query
|
114
|
+
].reduce({}, :merge)
|
115
|
+
|
116
|
+
url = "/items/#{data.empty? ? '' : '?'}#{URI.encode_www_form(data)}"
|
117
|
+
@data = @api.request(url).map do |hash|
|
118
|
+
hash['id'] = @api.normalize_id(hash['id'])
|
119
|
+
hash
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Internal: Make a HTTP request to the ALD server to get a single item.
|
124
|
+
# Used by Collection#[].
|
125
|
+
#
|
126
|
+
# filter - a filter Hash as returned by #entry_filter
|
127
|
+
#
|
128
|
+
# Returns a Hash with all information about the item.
|
129
|
+
#
|
130
|
+
# Raises ArgumentError if the filters cannot be handled.
|
131
|
+
def request_entry(filter)
|
132
|
+
url = if filter.key?(:id)
|
133
|
+
"/items/#{filter[:id]}"
|
134
|
+
elsif %w[name version].all? { |k| filter.key?(k.to_sym) }
|
135
|
+
"/items/#{filter[:name]}/#{filter[:version]}"
|
136
|
+
else
|
137
|
+
raise ArgumentError
|
138
|
+
end
|
139
|
+
|
140
|
+
@api.request(url)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Internal: Used by Collection#each and Collection#[] to create new items.
|
144
|
+
#
|
145
|
+
# hash - a Hash describing the item, with the keys 'id', 'name'
|
146
|
+
# and 'version'.
|
147
|
+
# initialized - a Boolean indicating if the given Hash already contains
|
148
|
+
# all information about the item or only name and id.
|
149
|
+
def entry(hash, initialized = false)
|
150
|
+
@api.item(hash, initialized)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Internal: Implements item access for #[]. See Collection#entry_filter
|
154
|
+
# for more information.
|
155
|
+
#
|
156
|
+
# ItemCollection allows access by ID (String) or name and version
|
157
|
+
# (both String).
|
158
|
+
def entry_filter(args)
|
159
|
+
if args.length == 1 && args.first.is_a?(String)
|
160
|
+
{ id: @api.normalize_id(args.first) }
|
161
|
+
elsif args.length == 2
|
162
|
+
{ name: args.first, version: args.last }
|
163
|
+
else
|
164
|
+
raise ArgumentError
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|