dao 0.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +35 -0
- data/Rakefile +6 -3
- data/TODO +37 -0
- data/dao.gemspec +30 -0
- data/db/dao.yml +8 -0
- data/lib/dao.rb +84 -5
- data/lib/dao/active_record.rb +76 -0
- data/lib/dao/api.rb +9 -0
- data/lib/dao/api/context.rb +38 -0
- data/lib/dao/api/dsl.rb +50 -0
- data/lib/dao/api/endpoints.rb +190 -0
- data/lib/dao/api/initializers.rb +71 -0
- data/lib/dao/api/modes.rb +85 -0
- data/lib/dao/blankslate.rb +5 -0
- data/lib/dao/data.rb +58 -0
- data/lib/dao/db.rb +183 -0
- data/lib/dao/endpoint.rb +16 -0
- data/lib/dao/engine.rb +7 -0
- data/lib/dao/errors.rb +238 -0
- data/lib/dao/exceptions.rb +2 -0
- data/lib/dao/form.rb +236 -0
- data/lib/dao/mode.rb +41 -0
- data/lib/dao/mongo_mapper.rb +70 -0
- data/lib/dao/params.rb +109 -0
- data/lib/dao/path.rb +149 -0
- data/lib/dao/rails.rb +15 -0
- data/lib/dao/rails/app/api.rb +55 -0
- data/lib/dao/rails/app/controllers/api_controller.rb +99 -0
- data/lib/dao/rails/lib/generators/dao/USAGE +9 -0
- data/lib/dao/rails/lib/generators/dao/api_generator.rb +3 -0
- data/lib/dao/rails/lib/generators/dao/dao_generator.rb +27 -0
- data/lib/dao/rails/lib/generators/dao/templates/api.rb +55 -0
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +99 -0
- data/lib/dao/result.rb +87 -0
- data/lib/dao/slug.rb +11 -0
- data/lib/dao/status.rb +223 -0
- data/lib/dao/stdext.rb +10 -0
- data/lib/dao/support.rb +62 -0
- data/lib/dao/validations.rb +115 -0
- data/sample/rails_app/Gemfile +33 -0
- data/sample/rails_app/Gemfile.lock +88 -0
- data/sample/rails_app/README +1 -0
- data/sample/rails_app/Rakefile +7 -0
- data/sample/rails_app/app/api.rb +55 -0
- data/sample/rails_app/app/controllers/api_controller.rb +99 -0
- data/sample/rails_app/app/controllers/application_controller.rb +3 -0
- data/sample/rails_app/app/helpers/application_helper.rb +2 -0
- data/sample/rails_app/app/views/layouts/application.html.erb +14 -0
- data/sample/rails_app/config.ru +4 -0
- data/sample/rails_app/config/application.rb +51 -0
- data/sample/rails_app/config/boot.rb +13 -0
- data/sample/rails_app/config/database.yml +22 -0
- data/sample/rails_app/config/environment.rb +5 -0
- data/sample/rails_app/config/environments/development.rb +26 -0
- data/sample/rails_app/config/environments/production.rb +49 -0
- data/sample/rails_app/config/environments/test.rb +35 -0
- data/sample/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/sample/rails_app/config/initializers/inflections.rb +10 -0
- data/sample/rails_app/config/initializers/mime_types.rb +5 -0
- data/sample/rails_app/config/initializers/secret_token.rb +7 -0
- data/sample/rails_app/config/initializers/session_store.rb +8 -0
- data/sample/rails_app/config/locales/en.yml +5 -0
- data/sample/rails_app/config/routes.rb +62 -0
- data/sample/rails_app/db/development.sqlite3 +0 -0
- data/sample/rails_app/db/seeds.rb +7 -0
- data/sample/rails_app/doc/README_FOR_APP +2 -0
- data/sample/rails_app/log/development.log +27 -0
- data/sample/rails_app/log/production.log +0 -0
- data/sample/rails_app/log/server.log +0 -0
- data/sample/rails_app/log/test.log +0 -0
- data/sample/rails_app/public/404.html +26 -0
- data/sample/rails_app/public/422.html +26 -0
- data/sample/rails_app/public/500.html +26 -0
- data/sample/rails_app/public/favicon.ico +0 -0
- data/sample/rails_app/public/images/rails.png +0 -0
- data/sample/rails_app/public/index.html +239 -0
- data/sample/rails_app/public/javascripts/application.js +2 -0
- data/sample/rails_app/public/javascripts/controls.js +965 -0
- data/sample/rails_app/public/javascripts/dragdrop.js +974 -0
- data/sample/rails_app/public/javascripts/effects.js +1123 -0
- data/sample/rails_app/public/javascripts/prototype.js +6001 -0
- data/sample/rails_app/public/javascripts/rails.js +175 -0
- data/sample/rails_app/public/robots.txt +5 -0
- data/sample/rails_app/script/rails +6 -0
- data/sample/rails_app/test/performance/browsing_test.rb +9 -0
- data/sample/rails_app/test/test_helper.rb +13 -0
- data/test/dao_test.rb +271 -0
- data/test/helper.rb +15 -0
- data/test/testing.rb +74 -0
- metadata +137 -9
data/lib/dao/form.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
module Dao
|
2
|
+
class Form
|
3
|
+
include Tagz.globally
|
4
|
+
|
5
|
+
class << Form
|
6
|
+
def for(*args, &block)
|
7
|
+
new(*args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def cast(*args)
|
11
|
+
if args.size == 1
|
12
|
+
value = args.first
|
13
|
+
value.is_a?(self) ? value : self.for(value)
|
14
|
+
else
|
15
|
+
self.for(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :result
|
21
|
+
|
22
|
+
def initialize(*args, &block)
|
23
|
+
@result = args.shift if args.first.is_a?(Result)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def params
|
28
|
+
result.params
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
params.object_id == other.params.object_id
|
33
|
+
end
|
34
|
+
|
35
|
+
def errors
|
36
|
+
result.errors
|
37
|
+
end
|
38
|
+
|
39
|
+
def form(*args, &block)
|
40
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
41
|
+
keys = args.flatten
|
42
|
+
|
43
|
+
action = options.delete(:action) || './'
|
44
|
+
method = options.delete(:method) || 'post'
|
45
|
+
id = options.delete(:id) || id_for(keys)
|
46
|
+
klass = class_for(keys, options.delete(:class))
|
47
|
+
error = error_for(keys, options.delete(:error))
|
48
|
+
|
49
|
+
content =
|
50
|
+
if block.nil? and !options.has_key?(:content)
|
51
|
+
''
|
52
|
+
else
|
53
|
+
block ? block.call(form=self) : options.delete(:content)
|
54
|
+
end
|
55
|
+
|
56
|
+
form_(options_for(options, :action => action, :method => method, :class => klass, :id => id, :data_error => error)){ content }
|
57
|
+
end
|
58
|
+
|
59
|
+
def label(*args, &block)
|
60
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
61
|
+
keys = args.flatten
|
62
|
+
|
63
|
+
name = options.delete(:name) || keys.last
|
64
|
+
id = options.delete(:id) || id_for(keys)
|
65
|
+
klass = class_for(keys, options.delete(:class))
|
66
|
+
error = error_for(keys, options.delete(:error))
|
67
|
+
|
68
|
+
content =
|
69
|
+
if block.nil? and !options.has_key?(:content)
|
70
|
+
name.to_s.humanize
|
71
|
+
else
|
72
|
+
block ? block.call() : options.delete(:content)
|
73
|
+
end
|
74
|
+
|
75
|
+
label_(options_for(options, :name => name, :class => klass, :id => id, :data_error => error)){ content }
|
76
|
+
end
|
77
|
+
|
78
|
+
def input(*args, &block)
|
79
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
80
|
+
keys = args.flatten
|
81
|
+
|
82
|
+
type = options.delete(:type) || :text
|
83
|
+
name = options.delete(:name) || name_for(keys)
|
84
|
+
id = options.delete(:id) || id_for(keys)
|
85
|
+
klass = class_for(keys, options.delete(:class))
|
86
|
+
error = error_for(keys, options.delete(:error))
|
87
|
+
|
88
|
+
value =
|
89
|
+
if block.nil? and !options.has_key?(:value)
|
90
|
+
value_for(params, keys)
|
91
|
+
else
|
92
|
+
block ? block.call(params.get(keys)) : options.delete(:value)
|
93
|
+
end
|
94
|
+
|
95
|
+
input_(options_for(options, :type => type, :name => name, :value => value, :class => klass, :id => id, :data_error => error)){}
|
96
|
+
end
|
97
|
+
|
98
|
+
def submit(*args, &block)
|
99
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
100
|
+
options[:type] = :submit
|
101
|
+
options[:value] = block ? block.call : :Submit
|
102
|
+
args.push(options)
|
103
|
+
input(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
def button(*args)
|
107
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
108
|
+
keys = args.flatten
|
109
|
+
|
110
|
+
type = options.delete(:type) || :button
|
111
|
+
name = options.delete(:name) || name_for(keys)
|
112
|
+
id = options.delete(:id) || id_for(keys)
|
113
|
+
klass = class_for(keys, options.delete(:class))
|
114
|
+
error = error_for(keys, options.delete(:error))
|
115
|
+
|
116
|
+
value =
|
117
|
+
if block.nil? and !options.has_key?(:value)
|
118
|
+
value_for(params, keys)
|
119
|
+
else
|
120
|
+
block ? block.call(params.get(keys)) : options.delete(:value)
|
121
|
+
end
|
122
|
+
|
123
|
+
button_(options_for(options, :type => type, :name => name, :value => value, :class => klass, :id => id, :data_error => error)){}
|
124
|
+
end
|
125
|
+
|
126
|
+
def reset(*args)
|
127
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
128
|
+
options[:type] = :reset
|
129
|
+
args.push(options)
|
130
|
+
button(*args)
|
131
|
+
end
|
132
|
+
|
133
|
+
def textarea(*args, &block)
|
134
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
135
|
+
keys = args.flatten
|
136
|
+
|
137
|
+
name = options.delete(:name) || name_for(keys)
|
138
|
+
id = options.delete(:id) || id_for(keys)
|
139
|
+
klass = class_for(keys, options.delete(:class))
|
140
|
+
error = error_for(keys, options.delete(:error))
|
141
|
+
|
142
|
+
value =
|
143
|
+
if block.nil? and !options.has_key?(:value)
|
144
|
+
value_for(params, keys)
|
145
|
+
else
|
146
|
+
block ? block.call(params.get(keys)) : options.delete(:value)
|
147
|
+
end
|
148
|
+
|
149
|
+
textarea_(options_for(options, :name => name, :class => klass, :id => id, :data_error => error)){ value }
|
150
|
+
end
|
151
|
+
|
152
|
+
def select(*args, &block)
|
153
|
+
options = Dao.map_for(args.last.is_a?(Hash) ? args.pop : {})
|
154
|
+
keys = args.flatten
|
155
|
+
|
156
|
+
name = options.delete(:name) || name_for(keys)
|
157
|
+
from = options.delete(:from) || options.delete(:select) || options.delete(:all) || options.delete(:list)
|
158
|
+
|
159
|
+
id = options.delete(:id) || id_for(keys)
|
160
|
+
klass = class_for(keys, options.delete(:class))
|
161
|
+
error = error_for(keys, options.delete(:error))
|
162
|
+
|
163
|
+
select_(options_for(options, :name => name, :class => klass, :id => id, :data_error => error)){
|
164
|
+
pairs = Array(params[from]).flatten
|
165
|
+
pairs.each do |pair|
|
166
|
+
result = block.call(pair)
|
167
|
+
case result
|
168
|
+
when Array
|
169
|
+
value, content, selected, *ignored = result
|
170
|
+
when Hash
|
171
|
+
value = result[:value]
|
172
|
+
content = result[:content] || value
|
173
|
+
selected = result[:selected]
|
174
|
+
else
|
175
|
+
value = result
|
176
|
+
content = result
|
177
|
+
selected = false
|
178
|
+
end
|
179
|
+
opts = {:value => value}
|
180
|
+
opts[:selected] = !!selected if selected
|
181
|
+
option_(opts){ content }
|
182
|
+
end
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
186
|
+
def id_for(keys)
|
187
|
+
id = [result.path, keys.join('-')].compact.join('_')
|
188
|
+
slug_for(id)
|
189
|
+
end
|
190
|
+
|
191
|
+
def class_for(keys, klass = nil)
|
192
|
+
klass =
|
193
|
+
if result.errors.on?(keys)
|
194
|
+
[klass, 'dao', 'errors'].compact.join(' ')
|
195
|
+
else
|
196
|
+
[klass, 'dao'].compact.join(' ')
|
197
|
+
end
|
198
|
+
klass
|
199
|
+
end
|
200
|
+
|
201
|
+
def error_for(keys, klass = nil)
|
202
|
+
if result.errors.on?(keys)
|
203
|
+
result.errors.get(keys)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def value_for(params, keys)
|
208
|
+
return nil unless params.has?(keys)
|
209
|
+
value = Tagz.escapeHTML(params.get(keys))
|
210
|
+
end
|
211
|
+
|
212
|
+
def name_for(keys)
|
213
|
+
"#{ result.path }(#{ Array(keys).flatten.compact.join(',') })"
|
214
|
+
end
|
215
|
+
|
216
|
+
def options_for(*hashes)
|
217
|
+
map = Map.new
|
218
|
+
hashes.flatten.each do |h|
|
219
|
+
h.each{|k,v| map[attr_for(k)] = v unless v.nil?}
|
220
|
+
end
|
221
|
+
map
|
222
|
+
end
|
223
|
+
|
224
|
+
def slug_for(string)
|
225
|
+
string = string.to_s
|
226
|
+
words = string.to_s.scan(%r/\w+/)
|
227
|
+
words.map!{|word| word.gsub(%r/[^0-9a-zA-Z_:-]/, '')}
|
228
|
+
words.delete_if{|word| word.nil? or word.strip.empty?}
|
229
|
+
words.join('-').downcase.sub(/_+$/, '')
|
230
|
+
end
|
231
|
+
|
232
|
+
def attr_for(string)
|
233
|
+
slug_for(string).gsub(/_/, '-')
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
data/lib/dao/mode.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Dao
|
2
|
+
class Mode < ::String
|
3
|
+
class << Mode
|
4
|
+
def for(mode)
|
5
|
+
mode.is_a?(Mode) ? mode : Mode.new(mode.to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
def list
|
9
|
+
List
|
10
|
+
end
|
11
|
+
|
12
|
+
def default
|
13
|
+
Mode.for(:read)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Verbs = %w( options get head post put delete trace connect )
|
18
|
+
|
19
|
+
Verbs.each do |verb|
|
20
|
+
const = verb.downcase.capitalize
|
21
|
+
unless const_defined?(const)
|
22
|
+
mode = Mode.for(verb.downcase)
|
23
|
+
const_set(const, mode)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Read = Get unless defined?(Read)
|
28
|
+
Write = Post unless defined?(Write)
|
29
|
+
|
30
|
+
List = Verbs + %w( read write )
|
31
|
+
|
32
|
+
List.each do |method|
|
33
|
+
const = method.downcase.capitalize
|
34
|
+
define_method(method){ const_get(const) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
super(Mode.for(other))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
begin
|
2
|
+
MongoMapper
|
3
|
+
rescue NameError
|
4
|
+
nil
|
5
|
+
end
|
6
|
+
|
7
|
+
if defined?(MongoMapper)
|
8
|
+
|
9
|
+
module MongoMapper
|
10
|
+
module ToDao
|
11
|
+
module ClassMethods
|
12
|
+
def to_dao(*args)
|
13
|
+
|
14
|
+
unless defined?(@to_dao)
|
15
|
+
@to_dao = column_names.map{|name| name.to_s}
|
16
|
+
end
|
17
|
+
|
18
|
+
unless args.empty?
|
19
|
+
@to_dao.clear
|
20
|
+
args.flatten.compact.each do |arg|
|
21
|
+
@to_dao.push(arg.to_s)
|
22
|
+
end
|
23
|
+
@to_dao.uniq!
|
24
|
+
@to_dao.map!{|name| name.to_s}
|
25
|
+
end
|
26
|
+
|
27
|
+
@to_dao
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module InstanceMethods
|
32
|
+
def to_dao(*args)
|
33
|
+
hash = Dao.hash
|
34
|
+
model = self.class
|
35
|
+
|
36
|
+
attrs = args.empty? ? model.to_dao : args
|
37
|
+
|
38
|
+
attrs.each do |attr|
|
39
|
+
value = send(attr)
|
40
|
+
|
41
|
+
if value.respond_to?(:to_dao)
|
42
|
+
hash[attr] = value.to_dao
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
if value.is_a?(Array)
|
47
|
+
hash[attr] = value.map{|val| val.respond_to?(:to_dao) ? val.to_dao : val}
|
48
|
+
next
|
49
|
+
end
|
50
|
+
|
51
|
+
hash[attr] = value
|
52
|
+
end
|
53
|
+
|
54
|
+
if hash.has_key?(:_id) and not hash.has_key?(:id)
|
55
|
+
hash[:id] = hash[:_id]
|
56
|
+
end
|
57
|
+
|
58
|
+
hash
|
59
|
+
end
|
60
|
+
alias_method 'to_h', 'to_dao'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
MongoMapper::Document::ClassMethods.send(:include, ToDao::ClassMethods)
|
65
|
+
MongoMapper::Document::InstanceMethods.send(:include, ToDao::InstanceMethods)
|
66
|
+
MongoMapper::EmbeddedDocument::ClassMethods.send(:include, ToDao::ClassMethods)
|
67
|
+
MongoMapper::EmbeddedDocument::InstanceMethods.send(:include, ToDao::InstanceMethods)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/lib/dao/params.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module Dao
|
2
|
+
class Params < ::Map
|
3
|
+
class << Params
|
4
|
+
def parse(prefix, params = {})
|
5
|
+
prefix = prefix.to_s
|
6
|
+
params = Map.new(params)
|
7
|
+
parsed = Params.new
|
8
|
+
parsed.update(params[prefix]) if params.has_key?(prefix)
|
9
|
+
|
10
|
+
re = %r/^ #{ Regexp.escape(prefix) } (?: [(] ([^)]+) [)] )? $/x
|
11
|
+
|
12
|
+
params.each do |key, value|
|
13
|
+
next unless(key.is_a?(String) or key.is_a?(Symbol))
|
14
|
+
key = key.to_s
|
15
|
+
matched, keys = re.match(key).to_a
|
16
|
+
next unless matched
|
17
|
+
next unless keys
|
18
|
+
keys = keys.strip.split(%r/\s*,\s*/).map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
|
19
|
+
parsed.set(keys => value)
|
20
|
+
end
|
21
|
+
|
22
|
+
parsed
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :api
|
27
|
+
attr_accessor :endpoint
|
28
|
+
attr_accessor :params
|
29
|
+
attr_accessor :result
|
30
|
+
|
31
|
+
def Params.for(*args, &block)
|
32
|
+
options = Dao.options_for!(args)
|
33
|
+
|
34
|
+
api = options[:api]
|
35
|
+
endpoint = options[:endpoint]
|
36
|
+
updates = options[:params]
|
37
|
+
|
38
|
+
params = new()
|
39
|
+
params.api = api
|
40
|
+
params.endpoint = endpoint
|
41
|
+
|
42
|
+
params.update(updates) if updates
|
43
|
+
|
44
|
+
params
|
45
|
+
end
|
46
|
+
|
47
|
+
def path
|
48
|
+
result.path if result
|
49
|
+
end
|
50
|
+
|
51
|
+
def status(*args)
|
52
|
+
result.status(*args) if result
|
53
|
+
end
|
54
|
+
def status=(value)
|
55
|
+
result.status=value if result
|
56
|
+
end
|
57
|
+
|
58
|
+
def errors
|
59
|
+
result.errors if result
|
60
|
+
end
|
61
|
+
|
62
|
+
def data
|
63
|
+
result.data if result
|
64
|
+
end
|
65
|
+
|
66
|
+
def validates(*args, &block)
|
67
|
+
result.validates(*args, &block) if result
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate(*args, &block)
|
71
|
+
result.validate(*args, &block) if result
|
72
|
+
end
|
73
|
+
|
74
|
+
def valid?
|
75
|
+
result.valid? if result
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate!
|
79
|
+
result.validate! if result
|
80
|
+
end
|
81
|
+
|
82
|
+
unless Object.new.respond_to?(:instance_exec)
|
83
|
+
module InstanceExecHelper; end
|
84
|
+
include InstanceExecHelper
|
85
|
+
|
86
|
+
def instance_exec(*args, &block)
|
87
|
+
begin
|
88
|
+
old_critical, Thread.critical = Thread.critical, true
|
89
|
+
n = 0
|
90
|
+
n += 1 while respond_to?(mname="__instance_exec_#{ n }__")
|
91
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
92
|
+
ensure
|
93
|
+
Thread.critical = old_critical
|
94
|
+
end
|
95
|
+
begin
|
96
|
+
ret = send(mname, *args)
|
97
|
+
ensure
|
98
|
+
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
99
|
+
end
|
100
|
+
ret
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def Dao.parse(*args, &block)
|
107
|
+
Params.parse(*args, &block)
|
108
|
+
end
|
109
|
+
end
|