dao 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +96 -17
- data/Rakefile +92 -43
- data/dao.gemspec +12 -8
- data/lib/dao.rb +33 -20
- data/lib/dao/active_record.rb +51 -43
- data/lib/dao/api.rb +1 -1
- data/lib/dao/api/context.rb +6 -6
- data/lib/dao/api/dsl.rb +2 -2
- data/lib/dao/api/interfaces.rb +232 -0
- data/lib/dao/api/modes.rb +9 -6
- data/lib/dao/data.rb +7 -0
- data/lib/dao/errors.rb +27 -30
- data/lib/dao/form.rb +52 -28
- data/lib/dao/instance_exec.rb +37 -0
- data/lib/dao/interface.rb +16 -0
- data/lib/dao/params.rb +48 -24
- data/lib/dao/path.rb +1 -1
- data/lib/dao/rails.rb +5 -2
- data/lib/dao/rails/app/api.rb +1 -1
- data/lib/dao/rails/lib/generators/dao/dao_generator.rb +12 -0
- data/lib/dao/rails/lib/generators/dao/templates/api.rb +7 -1
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +25 -0
- data/lib/dao/rails/lib/generators/dao/templates/dao.css +27 -0
- data/lib/dao/rails/lib/generators/dao/templates/dao.js +149 -0
- data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +10 -0
- data/lib/dao/result.rb +53 -14
- data/lib/dao/status.rb +162 -1
- data/lib/dao/stdext.rb +6 -0
- data/lib/dao/support.rb +10 -2
- data/lib/dao/validations.rb +338 -14
- data/sample/rails_app/pubic/javascripts/dao.js +148 -0
- data/test/dao_test.rb +18 -19
- metadata +29 -18
- data/TODO +0 -37
- data/db/dao.yml +0 -8
@@ -0,0 +1,148 @@
|
|
1
|
+
if(!window.Dao){
|
2
|
+
(function(){
|
3
|
+
window.Dao = {};
|
4
|
+
|
5
|
+
// pull jQuery off the CDN iff needed
|
6
|
+
//
|
7
|
+
!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.4.2.js"%3E%3C/script%3E'));
|
8
|
+
var jq = jQuery;
|
9
|
+
|
10
|
+
// ctor
|
11
|
+
//
|
12
|
+
Dao.Api = function(){
|
13
|
+
this.route = '' + Dao.Api.route;
|
14
|
+
this.result = null;
|
15
|
+
this.results = [];
|
16
|
+
this.mode = 'get';
|
17
|
+
this.method = Dao[this.mode];
|
18
|
+
};
|
19
|
+
Dao.Api.route = '/api';
|
20
|
+
Dao.Api.modes = ["options", "get", "head", "post", "put", "delete", "trace", "connect"];
|
21
|
+
|
22
|
+
// single call interface
|
23
|
+
//
|
24
|
+
Dao.Api.prototype.call = function(){
|
25
|
+
var api = this;
|
26
|
+
var options = {};
|
27
|
+
|
28
|
+
if(arguments.length == 1){
|
29
|
+
var arg = arguments[0];
|
30
|
+
|
31
|
+
if(typeof(arg)=='string'){
|
32
|
+
options.path = arg;
|
33
|
+
} else {
|
34
|
+
options = arg;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
if(arguments.length > 1){
|
39
|
+
options.path = arguments[0];
|
40
|
+
options.params = arguments[1];
|
41
|
+
options.success = arguments[2];
|
42
|
+
}
|
43
|
+
|
44
|
+
if(!options.path){
|
45
|
+
options.path = '/ping';
|
46
|
+
}
|
47
|
+
|
48
|
+
if(!options.params){
|
49
|
+
options.params = {};
|
50
|
+
}
|
51
|
+
|
52
|
+
if(!options.success){
|
53
|
+
options.success = function(result){
|
54
|
+
result = new Dao.Result(result);
|
55
|
+
api.result = result;
|
56
|
+
api.results.push(result);
|
57
|
+
};
|
58
|
+
}
|
59
|
+
|
60
|
+
var url = api.route + options.path;
|
61
|
+
|
62
|
+
var data = options.params;
|
63
|
+
|
64
|
+
var success = function(result){
|
65
|
+
var result = new Dao.Result(result);
|
66
|
+
if(options.success){
|
67
|
+
options.success(result);
|
68
|
+
} else {
|
69
|
+
api.result = result;
|
70
|
+
api.results.push(result);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
|
74
|
+
var ajax = {};
|
75
|
+
ajax.url = url;
|
76
|
+
ajax.data = data;
|
77
|
+
ajax.success = success;
|
78
|
+
|
79
|
+
Dao[api.mode](ajax);
|
80
|
+
return(api);
|
81
|
+
};
|
82
|
+
|
83
|
+
// meta-program api.read(..), api.post(...), ...
|
84
|
+
//
|
85
|
+
for(var i = 0; i < Dao.Api.modes.length; i++){
|
86
|
+
(function(){
|
87
|
+
var mode = Dao.Api.modes[i];
|
88
|
+
|
89
|
+
Dao.Api.prototype[mode] = function(){
|
90
|
+
var api = this;
|
91
|
+
var previous = api.mode;
|
92
|
+
api.mode = mode;
|
93
|
+
var returned = api.call.apply(api, arguments);
|
94
|
+
api.mode = previous;
|
95
|
+
return(returned);
|
96
|
+
};
|
97
|
+
})();
|
98
|
+
}
|
99
|
+
Dao.Api.prototype['read'] = Dao.Api.prototype['get'];
|
100
|
+
Dao.Api.prototype['write'] = Dao.Api.prototype['post'];
|
101
|
+
|
102
|
+
// a thin wrapper on results for now. TODO - make it smarter
|
103
|
+
//
|
104
|
+
Dao.Result = function(options){
|
105
|
+
this.path = options.path;
|
106
|
+
this.status = options.status;
|
107
|
+
this.errors = options.errors;
|
108
|
+
this.data = options.data;
|
109
|
+
|
110
|
+
//parts = ('' + this.status).split(/\s+/);
|
111
|
+
//this.status.code = parseInt(parts.shift());
|
112
|
+
//this.status.message = parts.join(' ');
|
113
|
+
};
|
114
|
+
|
115
|
+
// ajax utils
|
116
|
+
//
|
117
|
+
Dao.ajax = function(options){
|
118
|
+
var ajax = {};
|
119
|
+
ajax.type = options.type;
|
120
|
+
ajax.url = options.url;
|
121
|
+
ajax.dataType = 'json';
|
122
|
+
if(ajax.type == 'POST' || ajax.type == 'PUT'){
|
123
|
+
ajax.data = jq.toJSON(options.data || {});
|
124
|
+
} else {
|
125
|
+
ajax.data = (options.data || {});
|
126
|
+
};
|
127
|
+
ajax.contentType = (options.contentType || 'application/json; charset=utf-8');
|
128
|
+
ajax.success = (options.success || function(){});
|
129
|
+
jq.ajax(ajax);
|
130
|
+
};
|
131
|
+
|
132
|
+
// meta-program Api.get(...), Api.post(...)
|
133
|
+
//
|
134
|
+
for(var i = 0; i < Dao.Api.modes.length; i++){
|
135
|
+
(function(){
|
136
|
+
var mode = Dao.Api.modes[i];
|
137
|
+
|
138
|
+
Dao[mode] = function(options){
|
139
|
+
options.type = mode.toUpperCase();
|
140
|
+
Dao.ajax(options);
|
141
|
+
};
|
142
|
+
})();
|
143
|
+
}
|
144
|
+
|
145
|
+
Dao.api = new Dao.Api();
|
146
|
+
window.api = window.api || Dao.api;
|
147
|
+
}());
|
148
|
+
}
|
data/test/dao_test.rb
CHANGED
@@ -19,13 +19,13 @@ Testing Dao do
|
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
|
-
testing 'that apis can have callable
|
22
|
+
testing 'that apis can have callable interfaces added to them which accept params and return results' do
|
23
23
|
captured = []
|
24
24
|
|
25
25
|
api_class =
|
26
26
|
assert{
|
27
27
|
Dao.api do
|
28
|
-
|
28
|
+
interface(:foo) do |params, result|
|
29
29
|
captured.push(params, result)
|
30
30
|
end
|
31
31
|
end
|
@@ -35,20 +35,20 @@ Testing Dao do
|
|
35
35
|
assert{ result.is_a?(Hash) }
|
36
36
|
end
|
37
37
|
|
38
|
-
testing 'that
|
38
|
+
testing 'that interfaces are automatically called according to arity' do
|
39
39
|
api = assert{ Class.new(Dao.api) }
|
40
|
-
assert{ api.class_eval{
|
41
|
-
assert{ api.class_eval{
|
42
|
-
assert{ api.class_eval{
|
40
|
+
assert{ api.class_eval{ interface(:zero){|| result.update :args => [] } } }
|
41
|
+
assert{ api.class_eval{ interface(:one){|a| result.update :args => [a]} } }
|
42
|
+
assert{ api.class_eval{ interface(:two){|a,b| result.update :args => [a,b]} } }
|
43
43
|
|
44
44
|
assert{ api.new.call(:zero).args.size == 0 }
|
45
45
|
assert{ api.new.call(:one).args.size == 1 }
|
46
46
|
assert{ api.new.call(:two).args.size == 2 }
|
47
47
|
end
|
48
48
|
|
49
|
-
testing 'that
|
49
|
+
testing 'that interfaces have an auto-vivifying params/result' do
|
50
50
|
api = assert{ Class.new(Dao.api) }
|
51
|
-
assert{ api.class_eval{
|
51
|
+
assert{ api.class_eval{ interface(:foo){ params; result; } } }
|
52
52
|
result = assert{ api.new.call(:foo) }
|
53
53
|
assert{ result.path.to_s =~ /foo/ }
|
54
54
|
end
|
@@ -136,7 +136,7 @@ Testing Dao do
|
|
136
136
|
assert{
|
137
137
|
api_class =
|
138
138
|
Dao.api do
|
139
|
-
|
139
|
+
interface('/foobar'){
|
140
140
|
data.update(params)
|
141
141
|
}
|
142
142
|
end
|
@@ -185,7 +185,7 @@ Testing Dao do
|
|
185
185
|
testing 'that simple validations work' do
|
186
186
|
result = Dao::Result.new
|
187
187
|
assert{ result.validates(:password){|password| password=='haxor'} }
|
188
|
-
result.
|
188
|
+
result.data.set(:password, 'haxor')
|
189
189
|
assert{ result.valid? }
|
190
190
|
end
|
191
191
|
|
@@ -193,7 +193,7 @@ Testing Dao do
|
|
193
193
|
assert{
|
194
194
|
api_class =
|
195
195
|
Dao.api do
|
196
|
-
|
196
|
+
interface('/foobar'){
|
197
197
|
result.validates(:a)
|
198
198
|
params.validate(:b)
|
199
199
|
validates(:c)
|
@@ -209,19 +209,18 @@ Testing Dao do
|
|
209
209
|
#
|
210
210
|
testing 'that validations can be cleared and do not clobber manually added errors' do
|
211
211
|
result = Dao::Result.new
|
212
|
-
|
213
|
-
params = result.params
|
212
|
+
data = result.data
|
214
213
|
errors = result.errors
|
215
214
|
|
216
215
|
assert{ result.validates(:email){|email| email.to_s.split(/@/).size == 2} }
|
217
|
-
assert{ result.validates(:password){|password| password == '
|
216
|
+
assert{ result.validates(:password){|password| password == 'pa$$w0rd'} }
|
218
217
|
|
219
|
-
|
220
|
-
assert{ not result.valid? }
|
221
|
-
|
222
|
-
params.set(:password => 'haxor')
|
218
|
+
data.set(:email => 'ara@dojo4.com', :password => 'pa$$w0rd')
|
223
219
|
assert{ result.valid? }
|
224
220
|
|
221
|
+
data.set(:password => 'haxor')
|
222
|
+
assert{ !result.valid? }
|
223
|
+
|
225
224
|
errors.add(:name, 'ara')
|
226
225
|
assert{ not result.valid? }
|
227
226
|
end
|
@@ -234,7 +233,7 @@ Testing Dao do
|
|
234
233
|
Dao.api {
|
235
234
|
description 'foobar'
|
236
235
|
doc 'signature' => {'read' => '...', 'write' => '...'}
|
237
|
-
|
236
|
+
interface('/barfoo'){}
|
238
237
|
}
|
239
238
|
}
|
240
239
|
api_class_index = assert{ api_class.index.is_a?(Hash) }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dao
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 2.0.0
|
10
|
+
version: 2.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ara T. Howard
|
@@ -15,35 +15,39 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-22 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: tagz
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 87
|
30
30
|
segments:
|
31
|
+
- 8
|
32
|
+
- 2
|
31
33
|
- 0
|
32
|
-
version:
|
34
|
+
version: 8.2.0
|
33
35
|
type: :runtime
|
34
36
|
version_requirements: *id001
|
35
37
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
38
|
+
name: map
|
37
39
|
prerelease: false
|
38
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
|
-
- -
|
43
|
+
- - ~>
|
42
44
|
- !ruby/object:Gem::Version
|
43
|
-
hash:
|
45
|
+
hash: 21
|
44
46
|
segments:
|
45
|
-
-
|
46
|
-
|
47
|
+
- 2
|
48
|
+
- 6
|
49
|
+
- 1
|
50
|
+
version: 2.6.1
|
47
51
|
type: :runtime
|
48
52
|
version_requirements: *id002
|
49
53
|
- !ruby/object:Gem::Dependency
|
@@ -52,12 +56,14 @@ dependencies:
|
|
52
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
53
57
|
none: false
|
54
58
|
requirements:
|
55
|
-
- -
|
59
|
+
- - ~>
|
56
60
|
- !ruby/object:Gem::Version
|
57
|
-
hash:
|
61
|
+
hash: 17
|
58
62
|
segments:
|
59
63
|
- 0
|
60
|
-
|
64
|
+
- 7
|
65
|
+
- 9
|
66
|
+
version: 0.7.9
|
61
67
|
type: :runtime
|
62
68
|
version_requirements: *id003
|
63
69
|
description: "description: dao kicks the ass"
|
@@ -70,12 +76,12 @@ extra_rdoc_files: []
|
|
70
76
|
|
71
77
|
files:
|
72
78
|
- dao.gemspec
|
73
|
-
- db/dao.yml
|
74
79
|
- lib/dao/active_record.rb
|
75
80
|
- lib/dao/api/context.rb
|
76
81
|
- lib/dao/api/dsl.rb
|
77
82
|
- lib/dao/api/endpoints.rb
|
78
83
|
- lib/dao/api/initializers.rb
|
84
|
+
- lib/dao/api/interfaces.rb
|
79
85
|
- lib/dao/api/modes.rb
|
80
86
|
- lib/dao/api.rb
|
81
87
|
- lib/dao/blankslate.rb
|
@@ -86,6 +92,8 @@ files:
|
|
86
92
|
- lib/dao/errors.rb
|
87
93
|
- lib/dao/exceptions.rb
|
88
94
|
- lib/dao/form.rb
|
95
|
+
- lib/dao/instance_exec.rb
|
96
|
+
- lib/dao/interface.rb
|
89
97
|
- lib/dao/mode.rb
|
90
98
|
- lib/dao/mongo_mapper.rb
|
91
99
|
- lib/dao/params.rb
|
@@ -96,6 +104,9 @@ files:
|
|
96
104
|
- lib/dao/rails/lib/generators/dao/dao_generator.rb
|
97
105
|
- lib/dao/rails/lib/generators/dao/templates/api.rb
|
98
106
|
- lib/dao/rails/lib/generators/dao/templates/api_controller.rb
|
107
|
+
- lib/dao/rails/lib/generators/dao/templates/dao.css
|
108
|
+
- lib/dao/rails/lib/generators/dao/templates/dao.js
|
109
|
+
- lib/dao/rails/lib/generators/dao/templates/dao_helper.rb
|
99
110
|
- lib/dao/rails/lib/generators/dao/USAGE
|
100
111
|
- lib/dao/rails.rb
|
101
112
|
- lib/dao/result.rb
|
@@ -136,6 +147,7 @@ files:
|
|
136
147
|
- sample/rails_app/log/production.log
|
137
148
|
- sample/rails_app/log/server.log
|
138
149
|
- sample/rails_app/log/test.log
|
150
|
+
- sample/rails_app/pubic/javascripts/dao.js
|
139
151
|
- sample/rails_app/public/404.html
|
140
152
|
- sample/rails_app/public/422.html
|
141
153
|
- sample/rails_app/public/500.html
|
@@ -157,7 +169,6 @@ files:
|
|
157
169
|
- test/dao_test.rb
|
158
170
|
- test/helper.rb
|
159
171
|
- test/testing.rb
|
160
|
-
- TODO
|
161
172
|
has_rdoc: true
|
162
173
|
homepage: http://github.com/ahoward/dao
|
163
174
|
licenses: []
|
data/TODO
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
todo:
|
2
|
-
|
3
|
-
route -> path??
|
4
|
-
|
5
|
-
- nested AR conversions
|
6
|
-
to_dao(:a, :b => [:foo, :bar])
|
7
|
-
|
8
|
-
- AR as_dao contains the model type/class.name
|
9
|
-
|
10
|
-
|
11
|
-
done:
|
12
|
-
- engine-ify the rails stuff? or what
|
13
|
-
- generator api
|
14
|
-
- controller
|
15
|
-
- helper
|
16
|
-
- json/pretty fix baked in? (yajl might simply this...)
|
17
|
-
- description/doc logic
|
18
|
-
- api.index
|
19
|
-
- to_alpo -> to_dao
|
20
|
-
- tests!
|
21
|
-
- #call auto parses data iff appropriate
|
22
|
-
@result = api.read.call('/posts/new(', params) ### check keys for '/posts/new'
|
23
|
-
- re-visit how parameters are parsed, perhaps we just use rack?
|
24
|
-
- next 'data' => {}
|
25
|
-
- check the db layer
|
26
|
-
- make sure one can call route based method (/foo/:bar) methods with params...
|
27
|
-
- Path==Route ??
|
28
|
-
- add result.rb, params.rb
|
29
|
-
- name -> path
|
30
|
-
- tagz for html methods?
|
31
|
-
- data aquires the name/path of the method?
|
32
|
-
- endpoints are objects that respond to call. namespaces respond to call.
|
33
|
-
api responds to call
|
34
|
-
- nested namespaces
|
35
|
-
- routing for path_info + mode
|
36
|
-
route(path_info, :mode => mode, :params => params)
|
37
|
-
- call() on namespaces AND endpoints... why?
|