dao 3.3.0 → 4.2.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.
- data/README +7 -0
- data/Rakefile +36 -17
- data/b.rb +38 -0
- data/dao.gemspec +41 -13
- data/lib/dao.rb +44 -13
- data/lib/dao/api.rb +1 -1
- data/lib/dao/api/context.rb +35 -45
- data/lib/dao/api/endpoints.rb +225 -91
- data/lib/dao/conducer.rb +437 -0
- data/lib/dao/conducer/attributes.rb +21 -0
- data/lib/dao/conducer/crud.rb +70 -0
- data/lib/dao/current.rb +66 -0
- data/lib/dao/db.rb +44 -5
- data/lib/dao/endpoint.rb +13 -1
- data/lib/dao/errors.rb +74 -59
- data/lib/dao/exceptions.rb +1 -2
- data/lib/dao/extractor.rb +68 -0
- data/lib/dao/form.rb +139 -46
- data/lib/dao/image_cache.rb +193 -0
- data/lib/dao/instance_exec.rb +1 -1
- data/lib/dao/name.rb +7 -0
- data/lib/dao/params.rb +16 -66
- data/lib/dao/rack.rb +3 -0
- data/lib/dao/rack/middleware.rb +5 -0
- data/lib/dao/rack/middleware/params_parser.rb +24 -0
- data/lib/dao/rails.rb +22 -5
- data/lib/dao/rails/lib/generators/dao/USAGE +2 -6
- data/lib/dao/rails/lib/generators/dao/dao_generator.rb +52 -7
- data/lib/dao/rails/lib/generators/dao/templates/api.rb +23 -7
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +24 -7
- data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +64 -0
- data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +79 -0
- data/lib/dao/rails/lib/generators/dao/templates/dao.js +13 -6
- data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +75 -11
- data/lib/dao/result.rb +1 -26
- data/lib/dao/slug.rb +37 -8
- data/lib/dao/status.rb +4 -0
- data/lib/dao/support.rb +155 -0
- data/lib/dao/validations.rb +48 -157
- data/lib/dao/validations/callback.rb +30 -0
- data/lib/dao/validations/common.rb +322 -320
- data/lib/dao/validations/validator.rb +219 -0
- data/test/active_model_conducer_lint_test.rb +19 -0
- data/test/api_test.rb +261 -0
- data/test/conducer_test.rb +205 -0
- data/test/db.yml +9 -0
- data/test/form_test.rb +42 -0
- data/test/support_test.rb +52 -0
- data/test/testing.rb +145 -24
- data/test/validations_test.rb +156 -0
- metadata +138 -21
- data/TODO +0 -33
- data/a.rb +0 -80
- data/db/dao.yml +0 -5
- data/lib/dao/api/interfaces.rb +0 -306
- data/lib/dao/interface.rb +0 -28
- data/lib/dao/presenter.rb +0 -129
- data/lib/dao/rails/lib/generators/dao/api_generator.rb +0 -3
- data/lib/dao/validations/base.rb +0 -68
- data/test/dao_test.rb +0 -506
data/lib/dao/api/interfaces.rb
DELETED
@@ -1,306 +0,0 @@
|
|
1
|
-
module Dao
|
2
|
-
class Api
|
3
|
-
# class methods
|
4
|
-
#
|
5
|
-
class << Api
|
6
|
-
def unload!
|
7
|
-
state.clear
|
8
|
-
end
|
9
|
-
|
10
|
-
def state
|
11
|
-
@state ||= {
|
12
|
-
:interfaces => {},
|
13
|
-
:blocks => {},
|
14
|
-
:README => [],
|
15
|
-
:docs => []
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
def interface(path, &block)
|
20
|
-
api = self
|
21
|
-
path = Path.new(path)
|
22
|
-
|
23
|
-
route = routes.add(path) if Route.like?(path)
|
24
|
-
|
25
|
-
interface = Interface.new({
|
26
|
-
'api' => api,
|
27
|
-
'path' => path,
|
28
|
-
'route' => route,
|
29
|
-
'block' => block,
|
30
|
-
'doc' => docs.pop
|
31
|
-
})
|
32
|
-
|
33
|
-
interfaces[path] = interface
|
34
|
-
end
|
35
|
-
alias_method('call', 'interface')
|
36
|
-
|
37
|
-
def interfaces
|
38
|
-
state[:interfaces]
|
39
|
-
end
|
40
|
-
|
41
|
-
def description(*args)
|
42
|
-
doc(:description => lines_for(*args))
|
43
|
-
end
|
44
|
-
alias_method('desc', 'description')
|
45
|
-
|
46
|
-
def doc(*args)
|
47
|
-
docs.push(Map[:description, nil]) if docs.empty?
|
48
|
-
doc = docs.last
|
49
|
-
options = Dao.options_for!(args)
|
50
|
-
if options.empty?
|
51
|
-
options[:description] = lines_for(*args)
|
52
|
-
end
|
53
|
-
doc.update(options)
|
54
|
-
doc
|
55
|
-
end
|
56
|
-
|
57
|
-
def docs
|
58
|
-
state[:docs]
|
59
|
-
end
|
60
|
-
|
61
|
-
def readme(*args)
|
62
|
-
if args.empty?
|
63
|
-
state[:README]
|
64
|
-
else
|
65
|
-
state[:README] = lines_for(args)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
alias_method('README', 'readme')
|
69
|
-
|
70
|
-
def lines_for(*args)
|
71
|
-
Dao.unindent(args.flatten.compact.join("\n")).split(/\n/)
|
72
|
-
end
|
73
|
-
|
74
|
-
def readme=(readme)
|
75
|
-
self.readme = readme.to_s
|
76
|
-
end
|
77
|
-
|
78
|
-
def index
|
79
|
-
index = Map.new
|
80
|
-
index[:README] = readme
|
81
|
-
interfaces.each do |path, interface|
|
82
|
-
index[path] = interface.doc || {'description' => ''}
|
83
|
-
end
|
84
|
-
index
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# instance methods
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
# call support
|
93
|
-
#
|
94
|
-
def call(path = '/index', params = {}, options = {})
|
95
|
-
api = self
|
96
|
-
path = Path.new(path)
|
97
|
-
interface = interfaces[path] ### interfaces.by_path(path)
|
98
|
-
route = nil
|
99
|
-
|
100
|
-
unless interface
|
101
|
-
route = route_for(path)
|
102
|
-
interface = interfaces[route]
|
103
|
-
end
|
104
|
-
|
105
|
-
unless interface
|
106
|
-
return index if path == '/index'
|
107
|
-
raise(NameError, "NO SUCH INTERFACE: #{ path }")
|
108
|
-
end
|
109
|
-
|
110
|
-
if route
|
111
|
-
params.update(route.params_for(path))
|
112
|
-
path = route.path_for(params)
|
113
|
-
else
|
114
|
-
if Route.like?(path)
|
115
|
-
route = Route.new(path)
|
116
|
-
path = route.path_for(params)
|
117
|
-
else
|
118
|
-
route = path
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
context = Context.for(api, route, path, interface, params, options)
|
123
|
-
|
124
|
-
callstack(context) do
|
125
|
-
catching(:result) do
|
126
|
-
context.call()
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
context.result
|
131
|
-
end
|
132
|
-
|
133
|
-
# lookup a route
|
134
|
-
#
|
135
|
-
def route_for(*args)
|
136
|
-
self.class.routes.match(*args)
|
137
|
-
end
|
138
|
-
|
139
|
-
# context support
|
140
|
-
#
|
141
|
-
def callstack(context = nil, &block)
|
142
|
-
@callstack ||= []
|
143
|
-
|
144
|
-
if block and context
|
145
|
-
begin
|
146
|
-
@callstack.push(context)
|
147
|
-
return block.call()
|
148
|
-
ensure
|
149
|
-
@callstack.pop
|
150
|
-
end
|
151
|
-
else
|
152
|
-
@callstack
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def context
|
157
|
-
callstack.last || raise('no context!')
|
158
|
-
end
|
159
|
-
|
160
|
-
def context?
|
161
|
-
!!callstack.last
|
162
|
-
end
|
163
|
-
|
164
|
-
def catching(label = :result, &block)
|
165
|
-
@catching ||= []
|
166
|
-
|
167
|
-
if block
|
168
|
-
begin
|
169
|
-
@catching.push(label)
|
170
|
-
catch(label, &block)
|
171
|
-
ensure
|
172
|
-
@catching.pop
|
173
|
-
end
|
174
|
-
else
|
175
|
-
@catching.last
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def return!(*value)
|
180
|
-
throw(:result, *value)
|
181
|
-
end
|
182
|
-
|
183
|
-
def catching_results(&block)
|
184
|
-
catching(:result, &block)
|
185
|
-
end
|
186
|
-
|
187
|
-
def catching?
|
188
|
-
catching
|
189
|
-
end
|
190
|
-
|
191
|
-
def catching_results?
|
192
|
-
catching == :result
|
193
|
-
end
|
194
|
-
|
195
|
-
# delgate some methods to the context
|
196
|
-
#
|
197
|
-
Context.attrs.each do |method|
|
198
|
-
module_eval <<-__, __FILE__, __LINE__
|
199
|
-
def #{ method }(*args)
|
200
|
-
context.send(#{ method.inspect }, *args)
|
201
|
-
end
|
202
|
-
__
|
203
|
-
end
|
204
|
-
|
205
|
-
def status(*args)
|
206
|
-
context.status.update(*args) unless args.empty?
|
207
|
-
context.status
|
208
|
-
end
|
209
|
-
def status!(*args)
|
210
|
-
status.update(*args)
|
211
|
-
return!
|
212
|
-
end
|
213
|
-
|
214
|
-
def data(*args)
|
215
|
-
context.data.replace(*args) unless args.empty?
|
216
|
-
context.data
|
217
|
-
end
|
218
|
-
def data!(*args)
|
219
|
-
data(*args)
|
220
|
-
valid!
|
221
|
-
end
|
222
|
-
|
223
|
-
def params!(*args)
|
224
|
-
params.replace(*args)
|
225
|
-
valid!
|
226
|
-
end
|
227
|
-
|
228
|
-
def error!
|
229
|
-
result.error!
|
230
|
-
end
|
231
|
-
|
232
|
-
# delegate some methods to the params
|
233
|
-
#
|
234
|
-
Validations::Mixin.list.each do |method|
|
235
|
-
module_eval <<-__, __FILE__, __LINE__
|
236
|
-
def #{ method }(*args)
|
237
|
-
params.send(#{ method.inspect }, *args)
|
238
|
-
end
|
239
|
-
__
|
240
|
-
end
|
241
|
-
|
242
|
-
# misc
|
243
|
-
#
|
244
|
-
def index
|
245
|
-
self.class.index
|
246
|
-
end
|
247
|
-
|
248
|
-
def interfaces
|
249
|
-
self.class.interfaces
|
250
|
-
end
|
251
|
-
|
252
|
-
def respond_to?(*args)
|
253
|
-
super(*args) || super(Path.absolute_path_for(*args))
|
254
|
-
end
|
255
|
-
|
256
|
-
# immediate parameter parsing support
|
257
|
-
#
|
258
|
-
def parameter(*args, &block)
|
259
|
-
options = Map.options_for!(args)
|
260
|
-
|
261
|
-
keys = args + Array(options[:keys]) + Array(options[:or])
|
262
|
-
|
263
|
-
raise(ArgumentError, 'no keys') if keys.empty?
|
264
|
-
|
265
|
-
blank = Object.new.freeze
|
266
|
-
value = blank
|
267
|
-
|
268
|
-
keys.each do |key|
|
269
|
-
if params.has?(key)
|
270
|
-
value = params.get(key)
|
271
|
-
break unless value.to_s.strip.empty?
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
if value == blank
|
276
|
-
message =
|
277
|
-
case options[:error]
|
278
|
-
when nil, false
|
279
|
-
nil
|
280
|
-
when true
|
281
|
-
which = keys.map{|key| Array(key).join('.')}.join(' or ')
|
282
|
-
"#{ which } (parameter is blank)"
|
283
|
-
else
|
284
|
-
message = options[:error].to_s
|
285
|
-
end
|
286
|
-
errors.add(message) if message
|
287
|
-
|
288
|
-
status(options[:status]) if options[:status]
|
289
|
-
return! if options[:return!]
|
290
|
-
end
|
291
|
-
|
292
|
-
value == blank ? nil : value
|
293
|
-
end
|
294
|
-
alias_method('param', 'parameter')
|
295
|
-
|
296
|
-
def parameter!(*args, &block)
|
297
|
-
options = args.last.is_a?(Hash) ? Map.for(args.pop) : Map.new
|
298
|
-
args.push(options)
|
299
|
-
options[:error] = true unless options.has_key?(:error)
|
300
|
-
options[:return!] = true unless options.has_key?(:return!)
|
301
|
-
options[:status] = 412 unless options.has_key?(:status)
|
302
|
-
parameter(*args, &block)
|
303
|
-
end
|
304
|
-
alias_method('param!', 'parameter!')
|
305
|
-
end
|
306
|
-
end
|
data/lib/dao/interface.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Dao
|
2
|
-
class Interface
|
3
|
-
Attrs = %w( api path route block doc )
|
4
|
-
Attrs.each{|attr| attr_accessor(attr)}
|
5
|
-
|
6
|
-
def initialize(options = {})
|
7
|
-
update(options)
|
8
|
-
end
|
9
|
-
|
10
|
-
def update(options = {})
|
11
|
-
options.each do |key, val|
|
12
|
-
send("#{ key }=", val)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def arity
|
17
|
-
block.arity
|
18
|
-
end
|
19
|
-
|
20
|
-
def call(*args)
|
21
|
-
block.call(*args)
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_proc
|
25
|
-
block
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/dao/presenter.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
module Dao
|
2
|
-
class Presenter
|
3
|
-
include Tagz.globally
|
4
|
-
|
5
|
-
class << Presenter
|
6
|
-
def for(*args, &block)
|
7
|
-
new(*args, &block)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_accessor :result
|
12
|
-
attr_accessor :formats
|
13
|
-
|
14
|
-
def initialize(*args, &block)
|
15
|
-
@result = args.shift if args.first.is_a?(Result)
|
16
|
-
@formats = Map.new
|
17
|
-
end
|
18
|
-
|
19
|
-
%w( set get has has? [] ).each do |method|
|
20
|
-
module_eval <<-__, __FILE__, __LINE__
|
21
|
-
def #{ method }(*args, &block)
|
22
|
-
data.#{ method }(*args, &block)
|
23
|
-
end
|
24
|
-
__
|
25
|
-
end
|
26
|
-
|
27
|
-
def extend(*args, &block)
|
28
|
-
return super if block.nil?
|
29
|
-
singleton_class =
|
30
|
-
class << self
|
31
|
-
self
|
32
|
-
end
|
33
|
-
singleton_class.module_eval(&block)
|
34
|
-
end
|
35
|
-
|
36
|
-
def tag(*args, &block)
|
37
|
-
options = Dao.options_for!(args)
|
38
|
-
args.push(:div) if args.empty?
|
39
|
-
tagname = args.shift
|
40
|
-
keys = args
|
41
|
-
|
42
|
-
tag_method = "#{ tagname }_"
|
43
|
-
|
44
|
-
id = options.delete(:id) || id_for(keys)
|
45
|
-
klass = class_for(keys, options.delete(:class))
|
46
|
-
error = error_for(keys, options.delete(:error))
|
47
|
-
|
48
|
-
tag_options =
|
49
|
-
options_for(options, :id => id, :class => klass, :data_error => error)
|
50
|
-
|
51
|
-
value = value_for(keys)
|
52
|
-
tag_value = instance_exec(value, &format_for(keys))
|
53
|
-
|
54
|
-
send(tag_method, tag_options){ tag_value }
|
55
|
-
end
|
56
|
-
|
57
|
-
include InstanceExec
|
58
|
-
|
59
|
-
DefaultFormat = lambda{|value| value}
|
60
|
-
|
61
|
-
def format_for(keys)
|
62
|
-
formats.get(keys) || DefaultFormat
|
63
|
-
end
|
64
|
-
|
65
|
-
def format(list_of_keys, &block)
|
66
|
-
Array(list_of_keys).each do |keys|
|
67
|
-
formats.set(keys, block)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def data
|
72
|
-
result.data
|
73
|
-
end
|
74
|
-
|
75
|
-
def errors
|
76
|
-
result.errors
|
77
|
-
end
|
78
|
-
|
79
|
-
def ==(other)
|
80
|
-
result == other.result
|
81
|
-
end
|
82
|
-
|
83
|
-
def id_for(keys)
|
84
|
-
id = [result.path, keys.join('-')].compact.join('_')
|
85
|
-
slug_for(id)
|
86
|
-
end
|
87
|
-
|
88
|
-
def class_for(keys, klass = nil)
|
89
|
-
klass =
|
90
|
-
if result.errors.on?(keys)
|
91
|
-
[klass, 'dao', 'errors'].compact.join(' ')
|
92
|
-
else
|
93
|
-
[klass, 'dao'].compact.join(' ')
|
94
|
-
end
|
95
|
-
klass
|
96
|
-
end
|
97
|
-
|
98
|
-
def error_for(keys, klass = nil)
|
99
|
-
if result.errors.on?(keys)
|
100
|
-
result.errors.get(keys)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def value_for(keys)
|
105
|
-
return nil unless data.has?(keys)
|
106
|
-
value = Tagz.escapeHTML(data.get(keys))
|
107
|
-
end
|
108
|
-
|
109
|
-
def options_for(*hashes)
|
110
|
-
map = Map.new
|
111
|
-
hashes.flatten.each do |h|
|
112
|
-
h.each{|k,v| map[attr_for(k)] = v unless v.nil?}
|
113
|
-
end
|
114
|
-
map
|
115
|
-
end
|
116
|
-
|
117
|
-
def slug_for(string)
|
118
|
-
string = string.to_s
|
119
|
-
words = string.to_s.scan(%r/\w+/)
|
120
|
-
words.map!{|word| word.gsub(%r/[^0-9a-zA-Z_:-]/, '')}
|
121
|
-
words.delete_if{|word| word.nil? or word.strip.empty?}
|
122
|
-
words.join('-').downcase.sub(/_+$/, '')
|
123
|
-
end
|
124
|
-
|
125
|
-
def attr_for(string)
|
126
|
-
slug_for(string).gsub(/_/, '-')
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|