glass-api 0.1.2
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 +15 -0
- data/Gemfile +9 -0
- data/README.md +166 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/glass.js +283 -0
- data/app/controllers/glass/api_controller.rb +99 -0
- data/app/controllers/glass/application_controller.rb +12 -0
- data/app/controllers/glass/main_controller.rb +15 -0
- data/config/routes.rb +12 -0
- data/lib/generators/glass/install_generator.rb +19 -0
- data/lib/generators/glass/templates/initializer.erb +16 -0
- data/lib/generators/glass/uninstall_generator.rb +14 -0
- data/lib/glass.rb +9 -0
- data/lib/glass/config.rb +57 -0
- data/lib/glass/engine.rb +8 -0
- data/lib/glass/version.rb +3 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDhlNGI0MDllYjdjYjAxYjBiODlmYjdhNGM4YTdlZTkwYzllNGU5Mg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGFlYjRkODcyZDY3YWUwZDc5OGZjOTU2ZTRjMGQxYzA2ZTU5YjM5OQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWI4N2IwYjA4ZTY2ZDg5NWQ4ODIzZjdiZGFkNjk2NjM0NzM0NWI4ZmU5NzU0
|
10
|
+
M2U0YjZjYWU0NjUxMjJhNjM2M2M5NWQwNmU0ZjI1Yzg0MTViM2NlNDRmYzUw
|
11
|
+
ZDM5YWM3NjhkMzI4OGIzNjVkOTkzMThjMmM1NjcxZjk1OWNhMDA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDAwNzQ1ZjZkNTFjZDM1ZmU3ZDhmMTEzOWQyZjQ5YmM3YmJlMmVlY2Y2ZDA5
|
14
|
+
NDBkMTFmYmFhYmNjNjcxNDBmMDkzN2Q5ODgyODg0NzM4NGNhMzJjNzg2ZjM1
|
15
|
+
NjFhNGZmYzI3Y2Q3NjUyZDVlZjdkNGZlZTMwMzZmZTg3NTk5MzY=
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# Glass
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/glass-api)
|
4
|
+
[](https://travis-ci.org/TeamSBK/Glass)
|
6
|
+
[](https://coveralls.io/r/TeamSBK/Glass?branch=master)
|
8
|
+
|
9
|
+
Glass is a lightweight Rails Engine that is built to do all the heavy lifting from serving an API in your Rails Application.
|
10
|
+
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* CRUD for your models without a Controller
|
15
|
+
* Integrates quickly for all client-side Javascript frameworks (Ember, Backbone, Angular)
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
gem 'glass-api', require: 'glass'
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install glass-api
|
30
|
+
|
31
|
+
And then run:
|
32
|
+
|
33
|
+
rails generate glass:install
|
34
|
+
|
35
|
+
This generator will install Glass. It will also add an initializer in `config/initializer/glass.rb`
|
36
|
+
|
37
|
+
Glass.configure do |config|
|
38
|
+
config.models = ['User']
|
39
|
+
config.app_name = 'Test App'
|
40
|
+
config.format = :json
|
41
|
+
end
|
42
|
+
|
43
|
+
It will modify your `app/assets/javascripts/application.js`, adding:
|
44
|
+
|
45
|
+
//= require glass
|
46
|
+
|
47
|
+
It will modify your `config/routes.rb`, adding:
|
48
|
+
|
49
|
+
mount Glass::Engine => '/api', as: 'glass'
|
50
|
+
|
51
|
+
## Mongoid
|
52
|
+
|
53
|
+
class Model
|
54
|
+
include Mongoid::Document
|
55
|
+
def self.column_names
|
56
|
+
self.fields.collect { |field| field[0] }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
## Usage
|
61
|
+
|
62
|
+
#### Ruby
|
63
|
+
|
64
|
+
Start the server:
|
65
|
+
|
66
|
+
rails server
|
67
|
+
|
68
|
+
#### Javascript
|
69
|
+
|
70
|
+
The following usage examples makes use of the Glass API given that you have a
|
71
|
+
`User` model in your Rails app and you have configured the Glass gem to expose it.
|
72
|
+
|
73
|
+
###### Find
|
74
|
+
|
75
|
+
Finds a list of records in a model with 'Foo' as name.
|
76
|
+
|
77
|
+
```javascript
|
78
|
+
glass.User.find({
|
79
|
+
name: 'Foo'
|
80
|
+
}, function (res, error) {
|
81
|
+
if (!error) {
|
82
|
+
// Do something with res
|
83
|
+
}
|
84
|
+
});
|
85
|
+
```
|
86
|
+
|
87
|
+
|
88
|
+
###### Find All
|
89
|
+
|
90
|
+
The following usage example finds all users.
|
91
|
+
|
92
|
+
```javascript
|
93
|
+
glass.User.findAll(function (res, error) {
|
94
|
+
if (!error) {
|
95
|
+
// Do something with res
|
96
|
+
}
|
97
|
+
});
|
98
|
+
```
|
99
|
+
|
100
|
+
|
101
|
+
###### Create
|
102
|
+
|
103
|
+
Create a new user record.
|
104
|
+
|
105
|
+
```javascript
|
106
|
+
var user = {
|
107
|
+
name: 'Jaune Sarmiento',
|
108
|
+
email: 'hello@jaunesarmiento.me'
|
109
|
+
};
|
110
|
+
|
111
|
+
glass.User.create(user, function (res, error) {
|
112
|
+
if (!error) {
|
113
|
+
// Do something with res
|
114
|
+
}
|
115
|
+
});
|
116
|
+
```
|
117
|
+
|
118
|
+
###### Update
|
119
|
+
|
120
|
+
Update the user with `id == 1` and update its name to `Joko`.
|
121
|
+
|
122
|
+
```javascript
|
123
|
+
// Given our create() function returns the user object with 1 as id
|
124
|
+
var user = {
|
125
|
+
id: 1,
|
126
|
+
name: 'Joko'
|
127
|
+
};
|
128
|
+
|
129
|
+
glass.User.update(user, function (res, error) {
|
130
|
+
if (!error) {
|
131
|
+
// Do something with res
|
132
|
+
}
|
133
|
+
});
|
134
|
+
```
|
135
|
+
|
136
|
+
|
137
|
+
###### Delete
|
138
|
+
|
139
|
+
Delete a user record with `id == 1`.
|
140
|
+
|
141
|
+
```javascript
|
142
|
+
glass.User.delete(1, function (res, error) {
|
143
|
+
if (!error) {
|
144
|
+
// Do something with res
|
145
|
+
}
|
146
|
+
});
|
147
|
+
```
|
148
|
+
|
149
|
+
## Contributing
|
150
|
+
|
151
|
+
1. Fork it
|
152
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
153
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
154
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
155
|
+
5. Create new Pull Request
|
156
|
+
|
157
|
+
## License
|
158
|
+
|
159
|
+
MIT. See [License] for more details.
|
160
|
+
Copyright (c) 2013 TeamSBK. Powered by [Proudcloud] Inc.
|
161
|
+
|
162
|
+
|
163
|
+
[License]: http://github.com/TeamSBK/Glass/blob/master/LICENSE.txt
|
164
|
+
[Proudcloud]: http://www.proudcloud.net
|
165
|
+
|
166
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,283 @@
|
|
1
|
+
(function () {
|
2
|
+
|
3
|
+
// Glass core module
|
4
|
+
var Glass = Glass = function () {
|
5
|
+
this.init();
|
6
|
+
};
|
7
|
+
|
8
|
+
// Configuration settings
|
9
|
+
Glass.prototype.config = {};
|
10
|
+
|
11
|
+
// CSRF token
|
12
|
+
Glass.prototype.token = null;
|
13
|
+
|
14
|
+
// Model names
|
15
|
+
Glass.prototype.models = [];
|
16
|
+
|
17
|
+
// Initialization
|
18
|
+
Glass.prototype.init = function () {
|
19
|
+
// Get the CSRF token that will be used for all requests
|
20
|
+
this.token = this.getCsrfToken();
|
21
|
+
|
22
|
+
this.getConfig((function (config) {
|
23
|
+
if (config === undefined) throw new Error('Failed to get configuration data from the server.');
|
24
|
+
|
25
|
+
this.config = config;
|
26
|
+
|
27
|
+
var i = config.models.length;
|
28
|
+
while (i--) {
|
29
|
+
m = config.models[i];
|
30
|
+
Glass.prototype[m] = new this.Model(m, config.routes[m.toLowerCase()]);
|
31
|
+
Glass.prototype[m].token = this.token;
|
32
|
+
}
|
33
|
+
}).bind(this));
|
34
|
+
};
|
35
|
+
|
36
|
+
// Gets the CSRF token from the DOM
|
37
|
+
Glass.prototype.getCsrfToken = function () {
|
38
|
+
var token = document.querySelector('meta[name="csrf-token"]');
|
39
|
+
if (!token) throw new Error('Could not find CSRF token.');
|
40
|
+
else token = token.getAttribute('content');
|
41
|
+
|
42
|
+
return token;
|
43
|
+
};
|
44
|
+
|
45
|
+
// Fires an XHR to get the config data from the server
|
46
|
+
Glass.prototype.getConfig = function (callback) {
|
47
|
+
// Get the config from the server
|
48
|
+
this.get('/api', function (res, error) {
|
49
|
+
if (!error) {
|
50
|
+
var config = JSON.parse(res.response);
|
51
|
+
callback(config, error);
|
52
|
+
}
|
53
|
+
else {
|
54
|
+
callback(null, error);
|
55
|
+
}
|
56
|
+
}, false);
|
57
|
+
};
|
58
|
+
|
59
|
+
Glass.prototype.get = function (url, callback, async) {
|
60
|
+
this.doXHR('GET', url, callback, async);
|
61
|
+
};
|
62
|
+
|
63
|
+
Glass.prototype.post = function (url, callback, async) {
|
64
|
+
this.doXHR('POST', url, callback, async);
|
65
|
+
}
|
66
|
+
|
67
|
+
Glass.prototype.put = function (url, callback, async) {
|
68
|
+
this.doXHR('PUT', url, callback, async);
|
69
|
+
}
|
70
|
+
|
71
|
+
Glass.prototype.delete = function (url, callback, async) {
|
72
|
+
this.doXHR('DELETE', url, callback, async);
|
73
|
+
}
|
74
|
+
|
75
|
+
Glass.prototype.doXHR = function (type, url, callback, async) {
|
76
|
+
if (arguments.length < 3) throw new Error('Glass#doXHR is missing ' + (3 - arguments.length) + ' parameters.');
|
77
|
+
if (async === undefined) async = true;
|
78
|
+
|
79
|
+
// Append our CSRF token
|
80
|
+
url += ((url.indexOf('?') != -1) ? '&' : '?') + "authenticity_token=" + this.token;
|
81
|
+
|
82
|
+
var xhr = new XMLHttpRequest();
|
83
|
+
xhr.open(type, url, async);
|
84
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
85
|
+
|
86
|
+
xhr.onreadystatechange = (function () {
|
87
|
+
if (xhr.readyState == 4) {
|
88
|
+
if (xhr.status == 200 || xhr.status === 0) callback(xhr, null);
|
89
|
+
else callback(null, 'Could not complete XMLHttpRequest to ' + url);
|
90
|
+
}
|
91
|
+
}).bind(this);
|
92
|
+
|
93
|
+
xhr.send();
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
// Glass.Model module
|
98
|
+
var Model = Glass.prototype.Model = function (name, routes) {
|
99
|
+
this.init(name, routes);
|
100
|
+
|
101
|
+
// Let's add the XHR functions to our model as well
|
102
|
+
this.get = Glass.prototype.get;
|
103
|
+
this.post = Glass.prototype.post;
|
104
|
+
this.put = Glass.prototype.put;
|
105
|
+
this.delete = Glass.prototype.delete;
|
106
|
+
this.doXHR = Glass.prototype.doXHR;
|
107
|
+
};
|
108
|
+
|
109
|
+
Model.prototype.routes = null;
|
110
|
+
|
111
|
+
Model.prototype.name = null;
|
112
|
+
|
113
|
+
// Returns the total rows
|
114
|
+
Model.prototype.count = function () {};
|
115
|
+
|
116
|
+
// Model initialization
|
117
|
+
Model.prototype.init = function (name, routes) {
|
118
|
+
if (arguments.length < 2) throw new Error('Model#init() is missing ' + (2 - arguments.length) + ' parameters.');
|
119
|
+
|
120
|
+
// Build the model's routes
|
121
|
+
this.routes = routes;
|
122
|
+
|
123
|
+
// Set this model's name
|
124
|
+
this.name = name;
|
125
|
+
};
|
126
|
+
|
127
|
+
Model.prototype.findAll = function(callback) {
|
128
|
+
this.find({}, callback); // Just call Model#find() with a blank options
|
129
|
+
};
|
130
|
+
|
131
|
+
Model.prototype.find = function(options, callback) {
|
132
|
+
options || (options = {}); // providing no options means find all
|
133
|
+
|
134
|
+
var queryParams = this.serialize(options),
|
135
|
+
path = '/api' + this.routes['index'].path,
|
136
|
+
url = (queryParams.length > 0) ? path + '?' + queryParams : path;
|
137
|
+
|
138
|
+
this.get(url, function (res, error) {
|
139
|
+
if (!error) {
|
140
|
+
var result = JSON.parse(res.response);
|
141
|
+
if (callback) callback(result, null);
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
if (callback) callback(null, error);
|
145
|
+
}
|
146
|
+
});
|
147
|
+
};
|
148
|
+
|
149
|
+
Model.prototype.findOne = function(options, callback) {
|
150
|
+
// TODO: Find one record here; return first?
|
151
|
+
}
|
152
|
+
|
153
|
+
Model.prototype.findById = function(id, callback) {
|
154
|
+
if (typeof id == 'function' || id === undefined) throw new Error("Model#findbyId() is missing 'id' parameter.");
|
155
|
+
|
156
|
+
var route = this.routes['show'].path.replace(/:id/, id),
|
157
|
+
url = '/api' + route;
|
158
|
+
|
159
|
+
this.get(url, function (res, error) {
|
160
|
+
if (!error) {
|
161
|
+
var result = JSON.parse(res, error);
|
162
|
+
if (callback) callback(res.body, null);
|
163
|
+
}
|
164
|
+
else {
|
165
|
+
if (callback) callback(null, error);
|
166
|
+
}
|
167
|
+
});
|
168
|
+
}
|
169
|
+
|
170
|
+
Model.prototype.create = function(options, callback) {
|
171
|
+
if (typeof options == 'function' || options === undefined) throw new Error("Model#create() is missing 'options' parameter.");
|
172
|
+
|
173
|
+
var queryParams = this.serialize(options),
|
174
|
+
path = '/api' + this.routes['create'].path,
|
175
|
+
url = (queryParams.length > 0) ? path + '?' + queryParams : path;
|
176
|
+
|
177
|
+
this.post(url, function (res, error) {
|
178
|
+
if (!error) {
|
179
|
+
var result = JSON.parse(res.response);
|
180
|
+
if (callback) callback(result, null);
|
181
|
+
}
|
182
|
+
else {
|
183
|
+
if (callback) callback(null, error);
|
184
|
+
}
|
185
|
+
});
|
186
|
+
};
|
187
|
+
|
188
|
+
Model.prototype.update = function(options, callback) {
|
189
|
+
if (typeof options == 'function' || options === undefined) throw new Error("Model#update() is missing 'options' parameter.");
|
190
|
+
|
191
|
+
if (options.hasOwnProperty('id')) {
|
192
|
+
// Replace :id in our route with the value of id
|
193
|
+
var route = this.routes['update'].path.replace(/:id/, options.id);
|
194
|
+
delete options.id;
|
195
|
+
}
|
196
|
+
else {
|
197
|
+
throw new Error("Model#update() is missing 'options.id' parameter.");
|
198
|
+
}
|
199
|
+
|
200
|
+
var queryParams = this.serialize(options),
|
201
|
+
path = '/api' + route,
|
202
|
+
url = (queryParams.length > 0) ? path + '?' + queryParams : path;
|
203
|
+
|
204
|
+
this.put(url, function (res, error) {
|
205
|
+
if (!error) {
|
206
|
+
var result = JSON.parse(res.response);
|
207
|
+
if (callback) callback(result, null);
|
208
|
+
}
|
209
|
+
else {
|
210
|
+
if (callback) callback(null, error);
|
211
|
+
}
|
212
|
+
});
|
213
|
+
};
|
214
|
+
|
215
|
+
Model.prototype.delete = function(options, callback) {
|
216
|
+
if (typeof options == 'function' || options === undefined) throw new Error("Model#delete() is missing 'options' parameter.");
|
217
|
+
|
218
|
+
if (options.hasOwnProperty('id')) {
|
219
|
+
// Replace :id in our route with the value of id
|
220
|
+
var route = this.routes['destroy'].path.replace(/:id/, options.id);
|
221
|
+
delete options.id;
|
222
|
+
}
|
223
|
+
else {
|
224
|
+
throw new Error("Model#update() is missing 'options.id' parameter.");
|
225
|
+
}
|
226
|
+
|
227
|
+
var queryParams = this.serialize(options),
|
228
|
+
path = '/api' + route,
|
229
|
+
url = (queryParams.length > 0) ? path + '?' + queryParams : path;
|
230
|
+
|
231
|
+
this.delete(url, function (res, error) {
|
232
|
+
if (!error) {
|
233
|
+
var result = JSON.parse(res.response);
|
234
|
+
if (callback) callback(result, null);
|
235
|
+
}
|
236
|
+
else {
|
237
|
+
if (callback) callback(null, error);
|
238
|
+
}
|
239
|
+
});
|
240
|
+
};
|
241
|
+
|
242
|
+
Model.prototype.serialize = function (obj) {
|
243
|
+
var values = [],
|
244
|
+
prefix = '';
|
245
|
+
return this.recursiveSerialize(obj, values, prefix).join('&');
|
246
|
+
};
|
247
|
+
|
248
|
+
Model.prototype.recursiveSerialize = function(obj, values, prefix) {
|
249
|
+
for (var key in obj) {
|
250
|
+
if (typeof obj[key] == 'object') {
|
251
|
+
if (prefix.length == 0) prefix += '[' + key + ']';
|
252
|
+
else prefix += key;
|
253
|
+
|
254
|
+
values = this.recursiveSerialize(obj[key], values, prefix);
|
255
|
+
|
256
|
+
var prefixes = values.split('[');
|
257
|
+
|
258
|
+
if (prefixes.length > 1) prefix = prefixes.slice(0, prefixes.length - 1).join('[');
|
259
|
+
else prefix = prefixes[0];
|
260
|
+
}
|
261
|
+
else {
|
262
|
+
value = encodeURIComponent(obj[key]);
|
263
|
+
if (prefix.length > 0) var prefixedKey = prefix + '[' + key + ']';
|
264
|
+
else prefixedKey = key;
|
265
|
+
|
266
|
+
prefixedKey = encodeURIComponent(prefixedKey);
|
267
|
+
|
268
|
+
if (value) values.push(prefixedKey + '=' + value);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
return values;
|
273
|
+
};
|
274
|
+
|
275
|
+
|
276
|
+
// Add Glass.js to window
|
277
|
+
//window.addEventListener('load', function () {
|
278
|
+
//var g = new Glass();
|
279
|
+
//window['glass'] = g;
|
280
|
+
//}, false);
|
281
|
+
window.glass = new Glass();
|
282
|
+
|
283
|
+
}());
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Glass
|
2
|
+
class ApiController < Glass::ApplicationController
|
3
|
+
before_filter :sanitize_model
|
4
|
+
before_filter :sanitize_params, only: [:create, :update, :index]
|
5
|
+
before_filter :validate_model
|
6
|
+
|
7
|
+
respond_to :json
|
8
|
+
|
9
|
+
def index
|
10
|
+
begin
|
11
|
+
render json: all_or_where(@model) # See Private Method Below
|
12
|
+
rescue
|
13
|
+
|
14
|
+
@unknown_params = [].tap do |keys|
|
15
|
+
@new_hash.each do |key, val|
|
16
|
+
unless @model.column_names.include? key.to_s
|
17
|
+
keys << [key => val]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
render json: { unknown_parameters: @unknown_params.flatten }, status: :unprocessable_entity
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
begin
|
28
|
+
render json: @model.find(params[:id]).to_json
|
29
|
+
rescue Exception => exception
|
30
|
+
render json: "#{exception}", status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def create
|
35
|
+
object = @model.new(@new_hash)
|
36
|
+
|
37
|
+
if object.save
|
38
|
+
render json: object.to_json
|
39
|
+
else
|
40
|
+
render json: object.errors, status: :unprocessable_entity
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def update
|
45
|
+
begin
|
46
|
+
object = @model.find(params[:id])
|
47
|
+
rescue Exception => exception
|
48
|
+
render json: "#{exception}", status: :unprocessable_entity
|
49
|
+
end
|
50
|
+
|
51
|
+
if object.update_attributes(@new_hash)
|
52
|
+
render json: object.to_json
|
53
|
+
else
|
54
|
+
render json: object.errors, status: :unprocessable_entity
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def destroy
|
59
|
+
begin
|
60
|
+
object = @model.find(params[:id])
|
61
|
+
rescue Exception => exception
|
62
|
+
render json: "#{exception}", status: :unprocessable_entity
|
63
|
+
end
|
64
|
+
|
65
|
+
if object.delete
|
66
|
+
render json: 'Successfully deleted'
|
67
|
+
else
|
68
|
+
render json: 'Unable to delete entity', status: :unprocessable_entity
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def sanitize_model
|
74
|
+
@model = params[:model_scope].capitalize.singularize.constantize
|
75
|
+
end
|
76
|
+
|
77
|
+
def sanitize_params
|
78
|
+
@new_hash = {}
|
79
|
+
|
80
|
+
params.each do |key, value|
|
81
|
+
@new_hash[key.to_sym] = value unless ignored_keys.include? key
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_model
|
86
|
+
render json: "uninitialized constant #{@model}", status: :unprocessable_entity unless defined?(@model)
|
87
|
+
end
|
88
|
+
|
89
|
+
def ignored_keys
|
90
|
+
['utf', 'authenticity_token', 'id', 'controller', 'action', 'model_scope', 'api']
|
91
|
+
end
|
92
|
+
|
93
|
+
def all_or_where(model)
|
94
|
+
@new_hash.present? ? model.where(@new_hash).to_json : model.all.to_json
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Glass::Engine.routes.draw do
|
2
|
+
|
3
|
+
root to: 'main#index'
|
4
|
+
|
5
|
+
controller "api" do
|
6
|
+
get '/:model_scope', to: :index, as: 'index', via: 'get'
|
7
|
+
get '/:model_scope/:id', to: :show, as: 'show', via: 'get'
|
8
|
+
post '/:model_scope', to: :create, as: 'create', via: 'post'
|
9
|
+
put '/:model_scope/:id', to: :update, as: 'update', via: 'put'
|
10
|
+
delete '/:model_scope/:id', to: :delete, as: 'destroy', via: 'delete'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Glass
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
desc "Glass Installation"
|
8
|
+
|
9
|
+
def install
|
10
|
+
routes = File.open(Rails.root.join('config/routes.rb')).try :read
|
11
|
+
initializer = (File.open(Rails.root.join('config/initializers/glass.rb')) rescue nil).try :read
|
12
|
+
|
13
|
+
gsub_file "config/routes.rb", /mount Glass::Engine => \'api'\, as: :\'rails_admin\'/, ''
|
14
|
+
route("mount Glass::Engine => '/api', as: :glass")
|
15
|
+
|
16
|
+
template "initializer.erb", 'config/initializers/glass.rb' unless initializer
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Glass.configure do |config|
|
2
|
+
|
3
|
+
# Set the application name here
|
4
|
+
config.app_name = "<%= Rails.application.engine_name.titleize.chomp(' Application').gsub(' ','') %>"
|
5
|
+
|
6
|
+
# Set the models that would be included
|
7
|
+
# config.models = ['User']
|
8
|
+
|
9
|
+
# Set the format that would be used for this application. Default is json
|
10
|
+
config.format = :json
|
11
|
+
|
12
|
+
# Set the mountable path for Glass.js to recognize the URL
|
13
|
+
# Default is '/api'
|
14
|
+
config.mounted_at = '/api'
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Glass
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
desc "Glass Uninstalltion"
|
8
|
+
|
9
|
+
def uninstall
|
10
|
+
remove_file 'config/initializers/glass.rb'
|
11
|
+
gsub_file "config/routes.rb", /mount Glass::Engine => \'api'\, as: :\'rails_admin\'/, ''
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/glass.rb
ADDED
data/lib/glass/config.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Glass
|
2
|
+
module Config
|
3
|
+
class << self
|
4
|
+
attr_accessor :app_name
|
5
|
+
attr_accessor :models
|
6
|
+
attr_accessor :format
|
7
|
+
attr_accessor :mounted_at
|
8
|
+
attr_accessor :routes
|
9
|
+
attr_accessor :registry
|
10
|
+
|
11
|
+
def reset
|
12
|
+
@app_name = ''
|
13
|
+
@mounted_at = '/api'
|
14
|
+
@models = []
|
15
|
+
@format = :json
|
16
|
+
@routes = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def models_with_routes
|
20
|
+
@models.each do |model|
|
21
|
+
@routes[model.downcase.to_sym] = create_routes(model)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def pluralize_downcase(model)
|
26
|
+
model.pluralize.downcase
|
27
|
+
end
|
28
|
+
|
29
|
+
def capitalize_singularize(model)
|
30
|
+
model.capitalize.singularize
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_routes(model)
|
34
|
+
model_scope = pluralize_downcase(model)
|
35
|
+
model_name = capitalize_singularize(model)
|
36
|
+
|
37
|
+
return_routes(model_name, model_scope)
|
38
|
+
end
|
39
|
+
|
40
|
+
def return_routes(model_name, model_scope)
|
41
|
+
return {
|
42
|
+
"index" => { "type" => "get", "path" => "/#{model_scope}" },
|
43
|
+
"show" => { "type" => "get", "path" => "/#{model_scope}/:id" },
|
44
|
+
"create" => { "type" => "post", "path" => "/#{model_scope}" },
|
45
|
+
"update" => { "type" => "put", "path" => "/#{model_scope}/:id" },
|
46
|
+
"destroy" => { "type" => "delete","path" => "/#{model_scope}/:id" } }
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup
|
50
|
+
models_with_routes
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
self.reset
|
56
|
+
end
|
57
|
+
end
|
data/lib/glass/engine.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: glass-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adrian Peterson Co, Jaune Sarmiento, Robbie Marcelo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Glass - A lightweight Rails Engine for an open RESTful API for models
|
70
|
+
email:
|
71
|
+
- adrianpco@gmail.com, hawnecarlo@gmail.com, rbmrclo@hotmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- Gemfile
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- app/assets/javascripts/glass.js
|
80
|
+
- app/controllers/glass/api_controller.rb
|
81
|
+
- app/controllers/glass/application_controller.rb
|
82
|
+
- app/controllers/glass/main_controller.rb
|
83
|
+
- config/routes.rb
|
84
|
+
- lib/generators/glass/install_generator.rb
|
85
|
+
- lib/generators/glass/templates/initializer.erb
|
86
|
+
- lib/generators/glass/uninstall_generator.rb
|
87
|
+
- lib/glass/config.rb
|
88
|
+
- lib/glass/engine.rb
|
89
|
+
- lib/glass/version.rb
|
90
|
+
- lib/glass.rb
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.0.6
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Glass is a your one-stop solution for a RESTFUL API. It is a lightweight
|
115
|
+
Rails Engine that is built to do all the heavy lifting from serving an API in your
|
116
|
+
Rails Application.
|
117
|
+
test_files: []
|