bodhi-slam 0.3.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bodhi-slam.rb +2 -0
- data/lib/bodhi-slam/queries.rb +209 -0
- data/lib/bodhi-slam/resource.rb +83 -27
- data/lib/bodhi-slam/types.rb +1 -1
- data/lib/bodhi-slam/validators/multi.rb +5 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6df30b96a6aec463e6caa1ccbd279e47d27a57a2
|
4
|
+
data.tar.gz: 6852921c1be4570e84dab5869713af2f2f95bd81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a04d8bf2df4d929e2d533283610f9d93eef65479383250d93c91e4cd22a27ae2b1ed14fdbe3c476b1576561acd85b84bd19e0d9479c18c7a88a2e66ff892d6c
|
7
|
+
data.tar.gz: 1df3159b31651ba636903099ac5f7ac5c1dd85bca80866c7de94be3ba1be5ac52c7e34e387ecd1a1cd591a770f44f8b714d7356e6eeee081edc30395720e79eb
|
data/lib/bodhi-slam.rb
CHANGED
@@ -4,6 +4,7 @@ require "json"
|
|
4
4
|
require "time"
|
5
5
|
require "SecureRandom"
|
6
6
|
require 'regexp-examples'
|
7
|
+
require 'active_model'
|
7
8
|
|
8
9
|
require 'bodhi-slam/validations'
|
9
10
|
require 'bodhi-slam/errors'
|
@@ -16,6 +17,7 @@ require 'bodhi-slam/resource'
|
|
16
17
|
require 'bodhi-slam/types'
|
17
18
|
require 'bodhi-slam/users'
|
18
19
|
require 'bodhi-slam/profiles'
|
20
|
+
require 'bodhi-slam/queries'
|
19
21
|
|
20
22
|
class BodhiSlam
|
21
23
|
# Defines a context to interact with the Bodhi API
|
@@ -0,0 +1,209 @@
|
|
1
|
+
module Bodhi
|
2
|
+
class Query
|
3
|
+
attr_reader :klass, :url, :context, :criteria, :fields, :paging, :sorting
|
4
|
+
|
5
|
+
def initialize(klass)
|
6
|
+
@klass = Object.const_get(klass.to_s)
|
7
|
+
@criteria = []
|
8
|
+
@fields = []
|
9
|
+
@paging = {}
|
10
|
+
@sorting = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def clear!
|
14
|
+
@context = nil
|
15
|
+
@criteria.clear
|
16
|
+
@fields.clear
|
17
|
+
@paging.clear
|
18
|
+
@sorting.clear
|
19
|
+
end
|
20
|
+
|
21
|
+
def url
|
22
|
+
unless context.nil?
|
23
|
+
query = "/#{context.namespace}/resources/#{klass}?"
|
24
|
+
else
|
25
|
+
query = "/resources/#{klass}?"
|
26
|
+
end
|
27
|
+
params = []
|
28
|
+
|
29
|
+
unless criteria.empty?
|
30
|
+
if criteria.size > 1
|
31
|
+
where_string = "{$and:[#{criteria.join(',')}]}"
|
32
|
+
else
|
33
|
+
where_string = criteria.join
|
34
|
+
end
|
35
|
+
|
36
|
+
params << "where=#{where_string}"
|
37
|
+
end
|
38
|
+
|
39
|
+
unless fields.empty?
|
40
|
+
params << "fields=#{fields.join(',')}"
|
41
|
+
end
|
42
|
+
|
43
|
+
unless paging.empty?
|
44
|
+
paging_params = []
|
45
|
+
|
46
|
+
if paging[:page]
|
47
|
+
paging_params << "page:#{paging[:page]}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if paging[:limit]
|
51
|
+
paging_params << "limit:#{paging[:limit]}"
|
52
|
+
end
|
53
|
+
|
54
|
+
params << "paging=#{paging_params.join(',')}"
|
55
|
+
end
|
56
|
+
|
57
|
+
unless sorting.empty?
|
58
|
+
sort_params = []
|
59
|
+
|
60
|
+
if sorting[:field]
|
61
|
+
sort_params << sorting[:field]
|
62
|
+
end
|
63
|
+
|
64
|
+
if sorting[:order]
|
65
|
+
sort_params << sorting[:order]
|
66
|
+
end
|
67
|
+
|
68
|
+
params << "sort=#{sort_params.join(':')}"
|
69
|
+
end
|
70
|
+
|
71
|
+
query << params.join('&')
|
72
|
+
query.gsub(/\s+/, "")
|
73
|
+
end
|
74
|
+
|
75
|
+
def all
|
76
|
+
if context.nil?
|
77
|
+
raise ArgumentError.new("a Bodhi::Context is required to query the API")
|
78
|
+
end
|
79
|
+
|
80
|
+
if context.invalid?
|
81
|
+
raise Bodhi::ContextErrors.new(context.errors.messages), context.errors.to_a.to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
result = context.connection.get do |request|
|
85
|
+
request.url self.url
|
86
|
+
request.headers[context.credentials_header] = context.credentials
|
87
|
+
end
|
88
|
+
|
89
|
+
if result.status != 200
|
90
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
91
|
+
end
|
92
|
+
|
93
|
+
resources = JSON.parse(result.body)
|
94
|
+
resources.map{ |attributes| klass.factory.build(context, attributes) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def first
|
98
|
+
if context.nil?
|
99
|
+
raise ArgumentError.new("a Bodhi::Context is required to query the API")
|
100
|
+
end
|
101
|
+
|
102
|
+
if context.invalid?
|
103
|
+
raise Bodhi::ContextErrors.new(context.errors.messages), context.errors.to_a.to_s
|
104
|
+
end
|
105
|
+
|
106
|
+
result = context.connection.get do |request|
|
107
|
+
request.url self.url
|
108
|
+
request.headers[context.credentials_header] = context.credentials
|
109
|
+
end
|
110
|
+
|
111
|
+
if result.status != 200
|
112
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
113
|
+
end
|
114
|
+
|
115
|
+
resources = JSON.parse(result.body)
|
116
|
+
resources.map{ |attributes| klass.factory.build(context, attributes) }.first
|
117
|
+
end
|
118
|
+
|
119
|
+
def last
|
120
|
+
if context.nil?
|
121
|
+
raise ArgumentError.new("a Bodhi::Context is required to query the API")
|
122
|
+
end
|
123
|
+
|
124
|
+
if context.invalid?
|
125
|
+
raise Bodhi::ContextErrors.new(context.errors.messages), context.errors.to_a.to_s
|
126
|
+
end
|
127
|
+
|
128
|
+
result = context.connection.get do |request|
|
129
|
+
request.url self.url
|
130
|
+
request.headers[context.credentials_header] = context.credentials
|
131
|
+
end
|
132
|
+
|
133
|
+
if result.status != 200
|
134
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
135
|
+
end
|
136
|
+
|
137
|
+
resources = JSON.parse(result.body)
|
138
|
+
resources.map{ |attributes| klass.factory.build(context, attributes) }.last
|
139
|
+
end
|
140
|
+
|
141
|
+
def from(context)
|
142
|
+
unless context.is_a? Bodhi::Context
|
143
|
+
raise ArgumentError.new("Expected Bodhi::Context but received #{context.class}")
|
144
|
+
end
|
145
|
+
|
146
|
+
@context = context
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
def where(query)
|
151
|
+
unless query.is_a? String
|
152
|
+
raise ArgumentError.new("Expected String but received #{query.class}")
|
153
|
+
end
|
154
|
+
|
155
|
+
@criteria << query
|
156
|
+
@criteria.uniq!
|
157
|
+
self
|
158
|
+
end
|
159
|
+
alias :and :where
|
160
|
+
|
161
|
+
def select(field_names)
|
162
|
+
unless field_names.is_a? String
|
163
|
+
raise ArgumentError.new("Expected String but received #{field_names.class}")
|
164
|
+
end
|
165
|
+
|
166
|
+
fields_array = field_names.split(',')
|
167
|
+
@fields << fields_array
|
168
|
+
@fields.flatten!
|
169
|
+
@fields.uniq!
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
def limit(number)
|
174
|
+
unless number.is_a? Integer
|
175
|
+
raise ArgumentError.new("Expected Integer but received #{number.class}")
|
176
|
+
end
|
177
|
+
|
178
|
+
unless number <= 100
|
179
|
+
raise ArgumentError.new("Expected limit to be less than or equal to 100 but received #{number}")
|
180
|
+
end
|
181
|
+
|
182
|
+
@paging[:limit] = number
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
def page(number)
|
187
|
+
unless number.is_a? Integer
|
188
|
+
raise ArgumentError.new("Expected Integer but received #{number.class}")
|
189
|
+
end
|
190
|
+
|
191
|
+
@paging[:page] = number
|
192
|
+
self
|
193
|
+
end
|
194
|
+
|
195
|
+
def sort(field, order=nil)
|
196
|
+
unless field.is_a? String
|
197
|
+
raise ArgumentError.new("Expected String but received #{field.class}")
|
198
|
+
end
|
199
|
+
|
200
|
+
unless order.nil?
|
201
|
+
@sorting[:order] = order
|
202
|
+
end
|
203
|
+
|
204
|
+
@sorting[:field] = field
|
205
|
+
self
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
data/lib/bodhi-slam/resource.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Bodhi
|
2
2
|
module Resource
|
3
|
+
|
3
4
|
SYSTEM_ATTRIBUTES = [:sys_created_at, :sys_version, :sys_modified_at, :sys_modified_by,
|
4
5
|
:sys_namespace, :sys_created_by, :sys_type_version, :sys_id, :sys_embeddedType]
|
5
6
|
SUPPORT_ATTRIBUTES = [:bodhi_context, :errors]
|
@@ -62,8 +63,9 @@ module Bodhi
|
|
62
63
|
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
63
64
|
end
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
record = Object.const_get(name).new(JSON.parse(result.body))
|
67
|
+
record.bodhi_context = context
|
68
|
+
record
|
67
69
|
end
|
68
70
|
|
69
71
|
# Returns all records of the given resource from the Bodhi Cloud.
|
@@ -92,7 +94,7 @@ module Bodhi
|
|
92
94
|
records << JSON.parse(result.body)
|
93
95
|
end while records.size == 100
|
94
96
|
|
95
|
-
records.flatten.collect{ |record|
|
97
|
+
records.flatten.collect{ |record| Object.const_get(name).new(record) }
|
96
98
|
end
|
97
99
|
|
98
100
|
# Aggregates the given resource based on the supplied +pipeline+
|
@@ -120,30 +122,15 @@ module Bodhi
|
|
120
122
|
JSON.parse(result.body)
|
121
123
|
end
|
122
124
|
|
123
|
-
# Returns
|
125
|
+
# Returns a Bodhi::Query object for quering the given Resource
|
124
126
|
#
|
125
127
|
# context = Bodhi::Context.new
|
126
|
-
# Resource.where(
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
unless query.is_a? String
|
133
|
-
raise ArgumentError.new("Expected 'query' to be a String. 'query' #=> #{query.class}")
|
134
|
-
end
|
135
|
-
|
136
|
-
result = context.connection.get do |request|
|
137
|
-
request.url "/#{context.namespace}/resources/#{name}?where=#{query}"
|
138
|
-
request.headers[context.credentials_header] = context.credentials
|
139
|
-
end
|
140
|
-
|
141
|
-
if result.status != 200
|
142
|
-
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
143
|
-
end
|
144
|
-
|
145
|
-
resources = JSON.parse(result.body)
|
146
|
-
resources.map{ |attributes| factory.build(context, attributes) }
|
128
|
+
# Resource.where("{property: 'value'}").from(context).all
|
129
|
+
# Resource.where("{conditions}").and("{more conditions}").limit(10).from(context).all
|
130
|
+
def where(query)
|
131
|
+
query_obj = Bodhi::Query.new(name)
|
132
|
+
query_obj.where(query)
|
133
|
+
query_obj
|
147
134
|
end
|
148
135
|
|
149
136
|
# Deletes all records from a resource in the given +context+
|
@@ -167,6 +154,9 @@ module Bodhi
|
|
167
154
|
end
|
168
155
|
|
169
156
|
module InstanceMethods
|
157
|
+
def id; @sys_id; end
|
158
|
+
def persisted?; !@sys_id.nil?; end
|
159
|
+
|
170
160
|
# Returns a Hash of the Objects form attributes
|
171
161
|
#
|
172
162
|
# s = SomeResource.build({foo:"test", bar:12345})
|
@@ -181,7 +171,22 @@ module Bodhi
|
|
181
171
|
end
|
182
172
|
attributes
|
183
173
|
end
|
184
|
-
|
174
|
+
|
175
|
+
# Updates the resource with the given attributes Hash
|
176
|
+
#
|
177
|
+
# s = SomeResource.factory.build(foo:"test", bar:12345)
|
178
|
+
# s.attributes # => { foo: "test", bar: 12345 }
|
179
|
+
# s.update_attributes(foo:"12345", bar:10)
|
180
|
+
# s.attributes # => { foo: "12345", bar: 10 }
|
181
|
+
def update_attributes(params)
|
182
|
+
self.instance_variables.each do |variable|
|
183
|
+
attribute_name = variable.to_s.delete('@').to_sym
|
184
|
+
unless SYSTEM_ATTRIBUTES.include?(attribute_name) || SUPPORT_ATTRIBUTES.include?(attribute_name)
|
185
|
+
send("#{attribute_name}=", params[attribute_name])
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
185
190
|
# Returns all the Objects attributes as JSON.
|
186
191
|
# It converts any nested Objects to JSON if they respond to +to_json+
|
187
192
|
#
|
@@ -192,6 +197,34 @@ module Bodhi
|
|
192
197
|
attributes.to_json
|
193
198
|
end
|
194
199
|
|
200
|
+
# Saves the resource to the Bodhi Cloud. Returns true if record was saved
|
201
|
+
#
|
202
|
+
# obj = Resource.new
|
203
|
+
# obj.save # => true
|
204
|
+
# obj.persisted? # => true
|
205
|
+
def save
|
206
|
+
if self.invalid?
|
207
|
+
return false
|
208
|
+
end
|
209
|
+
|
210
|
+
result = bodhi_context.connection.post do |request|
|
211
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}"
|
212
|
+
request.headers['Content-Type'] = 'application/json'
|
213
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
214
|
+
request.body = attributes.to_json
|
215
|
+
end
|
216
|
+
|
217
|
+
if result.status != 201
|
218
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
219
|
+
end
|
220
|
+
|
221
|
+
if result.headers['location']
|
222
|
+
@sys_id = result.headers['location'].match(/(?<id>[a-zA-Z0-9]{24})/)[:id]
|
223
|
+
end
|
224
|
+
|
225
|
+
true
|
226
|
+
end
|
227
|
+
|
195
228
|
# Saves the resource to the Bodhi Cloud. Raises ArgumentError if record could not be saved.
|
196
229
|
#
|
197
230
|
# obj = Resouce.new
|
@@ -224,6 +257,29 @@ module Bodhi
|
|
224
257
|
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
225
258
|
end
|
226
259
|
end
|
260
|
+
alias :destroy :delete!
|
261
|
+
|
262
|
+
def update!(params)
|
263
|
+
update_attributes(params)
|
264
|
+
|
265
|
+
if invalid?
|
266
|
+
return false
|
267
|
+
end
|
268
|
+
|
269
|
+
result = bodhi_context.connection.put do |request|
|
270
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
|
271
|
+
request.headers['Content-Type'] = 'application/json'
|
272
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
273
|
+
request.body = params.to_json
|
274
|
+
end
|
275
|
+
|
276
|
+
if result.status != 204
|
277
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
278
|
+
end
|
279
|
+
|
280
|
+
true
|
281
|
+
end
|
282
|
+
alias :update :update!
|
227
283
|
|
228
284
|
def patch!(params)
|
229
285
|
result = bodhi_context.connection.patch do |request|
|
@@ -241,7 +297,7 @@ module Bodhi
|
|
241
297
|
|
242
298
|
def self.included(base)
|
243
299
|
base.extend(ClassMethods)
|
244
|
-
base.include(InstanceMethods, Bodhi::Validations)
|
300
|
+
base.include(InstanceMethods, Bodhi::Validations, ActiveModel::Model)
|
245
301
|
base.instance_variable_set(:@factory, Bodhi::Factory.new(base))
|
246
302
|
end
|
247
303
|
end
|
data/lib/bodhi-slam/types.rb
CHANGED
@@ -176,7 +176,7 @@ module Bodhi
|
|
176
176
|
})
|
177
177
|
|
178
178
|
type.properties.each_pair do |attr_name, attr_properties|
|
179
|
-
attr_properties.delete_if{ |key, value| ["system", "trim", "unique", "default", "isCurrentUser"].include?(key) }
|
179
|
+
attr_properties.delete_if{ |key, value| ["system", "trim", "unique", "default", "isCurrentUser", "toLower"].include?(key) }
|
180
180
|
klass.validates(attr_name.to_sym, attr_properties)
|
181
181
|
klass.factory.add_generator(attr_name.to_sym, attr_properties)
|
182
182
|
end
|
@@ -4,7 +4,11 @@ module Bodhi
|
|
4
4
|
def initialize(value); end
|
5
5
|
|
6
6
|
def validate(record, attribute, value)
|
7
|
-
|
7
|
+
if value.nil?
|
8
|
+
#do nothing
|
9
|
+
else
|
10
|
+
record.errors.add(attribute, "must be an array") unless value.is_a? Array
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
14
|
def to_options
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bodhi-slam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- willdavis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-http-persistent
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activemodel
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.2'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,6 +152,7 @@ files:
|
|
138
152
|
- lib/bodhi-slam/errors/context.rb
|
139
153
|
- lib/bodhi-slam/factory.rb
|
140
154
|
- lib/bodhi-slam/profiles.rb
|
155
|
+
- lib/bodhi-slam/queries.rb
|
141
156
|
- lib/bodhi-slam/resource.rb
|
142
157
|
- lib/bodhi-slam/types.rb
|
143
158
|
- lib/bodhi-slam/users.rb
|