apiql 0.3.6 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +31 -18
- data/apiql.gemspec +1 -1
- data/assets/javascripts/apiql.js +5 -5
- data/lib/apiql.rb +82 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0df2f76cbbbf87e6a3b506c598a7e41ef620dc283ddc345cd157d2fc80661848
|
4
|
+
data.tar.gz: c6a9b1b1af21e094684ce86ea61f2a26f1f8432ed00f4657f8272429bea3df22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b41c1af521d8feb114c107af996868d5d4a7ceaade3d20a4251c5881f8e54aeab5dbaf071c6a943650edaa00a21b066e9fea87b827bdbb9103d4a5fb128bab3c
|
7
|
+
data.tar.gz: 38d9b8b00bbf2cf92f940629b9fe76192aa1b702b5cf10364ba03d757c81eca0e5fbc21f3987391d08ea6ddb6ed4b2d5fe103e26a4bc59e9bbc216da8f834be8
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Implementation of the API language similar to GraphQL for Ruby on Rails.
|
|
4
4
|
|
5
5
|
It compiles requests into Hashes for faster rendering.
|
6
6
|
|
7
|
-
|
7
|
+
It automatically detects nested entities and eager-loads them for faster DB access!
|
8
8
|
|
9
9
|
Define your responder (requested methods):
|
10
10
|
|
@@ -31,16 +31,16 @@ class UserAPIQL < ::APIQL
|
|
31
31
|
end
|
32
32
|
|
33
33
|
```
|
34
|
-
In controller or Grape API endpoint, handler of POST /
|
34
|
+
In controller or Grape API endpoint, handler of POST /apiql method (or any other, see below APIQL.endpoint):
|
35
35
|
|
36
36
|
```ruby
|
37
|
-
def
|
37
|
+
def apiql
|
38
38
|
schema = APIQL.cache(params)
|
39
39
|
UserAPIQL.new(self, :session, :current_user, :params).render(schema)
|
40
40
|
end
|
41
41
|
|
42
42
|
```
|
43
|
-
variables `session`, `current_user` and `params` (you can list any you need) will be stored into context you can use in presenters and handlers
|
43
|
+
variables `session`, `current_user` and `params` (you can list any you need in your presenters/responders) will be stored into context you can use in presenters and handlers
|
44
44
|
|
45
45
|
Define presenters for your models:
|
46
46
|
|
@@ -66,14 +66,14 @@ assets/javascripts/application.js:
|
|
66
66
|
|
67
67
|
```javascript
|
68
68
|
//= require apiql
|
69
|
-
APIQL.endpoint = "/"
|
69
|
+
APIQL.endpoint = "/apiql"
|
70
70
|
```
|
71
71
|
|
72
72
|
```javascript
|
73
|
-
// function apiql(
|
73
|
+
// function apiql(schema, params = {}, form = null) -- schema is cached, so entire request is passed only for first time, later - short hashes only
|
74
74
|
|
75
75
|
authenticate(email, password) {
|
76
|
-
apiql(
|
76
|
+
apiql(`
|
77
77
|
logout()
|
78
78
|
|
79
79
|
authenticate(email, password) {
|
@@ -88,7 +88,7 @@ authenticate(email, password) {
|
|
88
88
|
}
|
89
89
|
}
|
90
90
|
`, {
|
91
|
-
email: email, // these
|
91
|
+
email: email, // these vars will be passed into methods on the server side
|
92
92
|
password: password
|
93
93
|
})
|
94
94
|
.then(response => { // response contains results of called methods
|
@@ -97,7 +97,7 @@ authenticate(email, password) {
|
|
97
97
|
}
|
98
98
|
|
99
99
|
logout() {
|
100
|
-
apiql(
|
100
|
+
apiql(`
|
101
101
|
logout
|
102
102
|
`)
|
103
103
|
.then(response => {
|
@@ -109,12 +109,12 @@ logout() {
|
|
109
109
|
you can call methods on entities:
|
110
110
|
|
111
111
|
```javascript
|
112
|
-
apiql(
|
112
|
+
apiql(`
|
113
113
|
authenticate(email, password) {
|
114
114
|
token
|
115
115
|
}
|
116
116
|
|
117
|
-
me.reload {
|
117
|
+
user: me.reload {
|
118
118
|
email full_name role token
|
119
119
|
|
120
120
|
roles(filter) {
|
@@ -132,7 +132,7 @@ you can call methods on entities:
|
|
132
132
|
password: password
|
133
133
|
})
|
134
134
|
.then(response => {
|
135
|
-
let user = response
|
135
|
+
let user = response.user
|
136
136
|
})
|
137
137
|
}
|
138
138
|
```
|
@@ -143,12 +143,6 @@ config/initializers/apiql.rb:
|
|
143
143
|
|
144
144
|
```ruby
|
145
145
|
class APIQL
|
146
|
-
delegate :authorize!, to: :@context
|
147
|
-
|
148
|
-
class Entity
|
149
|
-
delegate :authorize!, to: :@context
|
150
|
-
end
|
151
|
-
|
152
146
|
class Context
|
153
147
|
def authorize!(*args)
|
154
148
|
ability.authorize!(*args)
|
@@ -182,3 +176,22 @@ class User < ApplicationRecord
|
|
182
176
|
end
|
183
177
|
|
184
178
|
```
|
179
|
+
|
180
|
+
you can add CRUD methods for your models:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
class UserAPIQL < ::APIQL
|
184
|
+
model ::User
|
185
|
+
model ::Role
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
or mount methods from external modules:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
class UserAPIQL < ::APIQL
|
193
|
+
mount ::Services::User # all methouds could be called with "user" prefix like "user.logout()"
|
194
|
+
mount ::Services::Common, as: '' # all methods could be called without prefixes
|
195
|
+
mount ::Services::Employer, as: 'dashboard" # all methods could be called with specified prefix
|
196
|
+
end
|
197
|
+
```
|
data/apiql.gemspec
CHANGED
data/assets/javascripts/apiql.js
CHANGED
@@ -13,7 +13,7 @@ const APIQL = {
|
|
13
13
|
return hash
|
14
14
|
},
|
15
15
|
|
16
|
-
call(
|
16
|
+
call(schema, params = {}, form = null) {
|
17
17
|
return new Promise((resolve, reject) => {
|
18
18
|
if(params instanceof FormData) {
|
19
19
|
form = params
|
@@ -32,7 +32,7 @@ const APIQL = {
|
|
32
32
|
params.apiql = this.hash(schema)
|
33
33
|
}
|
34
34
|
|
35
|
-
Vue.http.post(
|
35
|
+
Vue.http.post(APIQL.endpoint, form || params)
|
36
36
|
.then(response => {
|
37
37
|
resolve(response.body)
|
38
38
|
})
|
@@ -50,7 +50,7 @@ const APIQL = {
|
|
50
50
|
params.apiql_request = schema
|
51
51
|
}
|
52
52
|
|
53
|
-
Vue.http.post(
|
53
|
+
Vue.http.post(APIQL.endpoint, form || params)
|
54
54
|
.then(response => {
|
55
55
|
resolve(response.body)
|
56
56
|
})
|
@@ -66,6 +66,6 @@ const APIQL = {
|
|
66
66
|
}
|
67
67
|
}
|
68
68
|
|
69
|
-
function apiql(
|
70
|
-
return APIQL.call(
|
69
|
+
function apiql(schema, params = {}, form = null) {
|
70
|
+
return APIQL.call(schema, params, form)
|
71
71
|
}
|
data/lib/apiql.rb
CHANGED
@@ -7,12 +7,90 @@ class APIQL
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
+
module CRUD
|
11
|
+
def model(klass)
|
12
|
+
define_method "#{klass.name.pluralize.underscore}" do |page = nil, page_size = 10|
|
13
|
+
authorize! :read, klass
|
14
|
+
|
15
|
+
if page.present?
|
16
|
+
{
|
17
|
+
total: klass.count,
|
18
|
+
items: klass.offset(page * page_size).limit(page_size)
|
19
|
+
}
|
20
|
+
else
|
21
|
+
klass.all
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
define_method "#{klass.name.underscore}" do |id|
|
26
|
+
item = klass.find(id)
|
27
|
+
|
28
|
+
authorize! :read, item
|
29
|
+
|
30
|
+
item
|
31
|
+
end
|
32
|
+
|
33
|
+
define_method "#{klass.name.underscore}.create" do |params|
|
34
|
+
authorize! :create, klass
|
35
|
+
|
36
|
+
klass_entity = "#{klass.name}::Entity".constantize
|
37
|
+
|
38
|
+
if klass_entity.respond_to?(:create_params, params)
|
39
|
+
params = klass_entity.send(:create_params, params)
|
40
|
+
elsif klass_entity.respond_to?(:params, params)
|
41
|
+
params = klass_entity.send(:params, params)
|
42
|
+
end
|
43
|
+
|
44
|
+
klass.create!(params)
|
45
|
+
end
|
46
|
+
|
47
|
+
define_method "#{klass.name.underscore}.update" do |id, params|
|
48
|
+
item = klass.find(id)
|
49
|
+
|
50
|
+
authorize! :update, item
|
51
|
+
|
52
|
+
klass_entity = "#{klass.name}::Entity".constantize
|
53
|
+
|
54
|
+
if klass_entity.respond_to?(:update_params, params)
|
55
|
+
params = klass_entity.send(:update_params, params)
|
56
|
+
elsif klass_entity.respond_to?(:params, params)
|
57
|
+
params = klass_entity.send(:params, params)
|
58
|
+
end
|
59
|
+
|
60
|
+
item.update!(params)
|
61
|
+
end
|
62
|
+
|
63
|
+
define_method "#{klass.name.underscore}.destroy" do |id|
|
64
|
+
item = klass.find(id)
|
65
|
+
|
66
|
+
authorize! :destroy, item
|
67
|
+
|
68
|
+
item.destroy!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
10
73
|
class Error < StandardError; end
|
11
74
|
class CacheMissed < StandardError; end
|
12
75
|
|
13
76
|
attr_reader :context
|
77
|
+
delegate :authorize!, to: :@context
|
14
78
|
|
15
79
|
class << self
|
80
|
+
include ::APIQL::CRUD
|
81
|
+
|
82
|
+
def mount(klass, as: nil)
|
83
|
+
as ||= klass.name.split('::').last.underscore
|
84
|
+
as += '.' if as.present?
|
85
|
+
|
86
|
+
klass.instance_methods(false).each do |method|
|
87
|
+
klass.alias_method("#{as}#{method}", method)
|
88
|
+
klass.remove_method(method) if as.present?
|
89
|
+
end
|
90
|
+
|
91
|
+
include klass
|
92
|
+
end
|
93
|
+
|
16
94
|
@@cache = {}
|
17
95
|
|
18
96
|
def cache(params)
|
@@ -185,6 +263,8 @@ class APIQL
|
|
185
263
|
private
|
186
264
|
|
187
265
|
class Entity
|
266
|
+
delegate :authorize!, to: :@context
|
267
|
+
|
188
268
|
class << self
|
189
269
|
attr_reader :apiql_attributes
|
190
270
|
|
@@ -350,6 +430,8 @@ class APIQL
|
|
350
430
|
end
|
351
431
|
end
|
352
432
|
|
433
|
+
def authorize!(*args); end
|
434
|
+
|
353
435
|
def inject_delegators(target)
|
354
436
|
@fields.each do |field|
|
355
437
|
target.class_eval do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apiql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Silchenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|