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.
Files changed (60) hide show
  1. data/README +7 -0
  2. data/Rakefile +36 -17
  3. data/b.rb +38 -0
  4. data/dao.gemspec +41 -13
  5. data/lib/dao.rb +44 -13
  6. data/lib/dao/api.rb +1 -1
  7. data/lib/dao/api/context.rb +35 -45
  8. data/lib/dao/api/endpoints.rb +225 -91
  9. data/lib/dao/conducer.rb +437 -0
  10. data/lib/dao/conducer/attributes.rb +21 -0
  11. data/lib/dao/conducer/crud.rb +70 -0
  12. data/lib/dao/current.rb +66 -0
  13. data/lib/dao/db.rb +44 -5
  14. data/lib/dao/endpoint.rb +13 -1
  15. data/lib/dao/errors.rb +74 -59
  16. data/lib/dao/exceptions.rb +1 -2
  17. data/lib/dao/extractor.rb +68 -0
  18. data/lib/dao/form.rb +139 -46
  19. data/lib/dao/image_cache.rb +193 -0
  20. data/lib/dao/instance_exec.rb +1 -1
  21. data/lib/dao/name.rb +7 -0
  22. data/lib/dao/params.rb +16 -66
  23. data/lib/dao/rack.rb +3 -0
  24. data/lib/dao/rack/middleware.rb +5 -0
  25. data/lib/dao/rack/middleware/params_parser.rb +24 -0
  26. data/lib/dao/rails.rb +22 -5
  27. data/lib/dao/rails/lib/generators/dao/USAGE +2 -6
  28. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +52 -7
  29. data/lib/dao/rails/lib/generators/dao/templates/api.rb +23 -7
  30. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +24 -7
  31. data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +64 -0
  32. data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +79 -0
  33. data/lib/dao/rails/lib/generators/dao/templates/dao.js +13 -6
  34. data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +75 -11
  35. data/lib/dao/result.rb +1 -26
  36. data/lib/dao/slug.rb +37 -8
  37. data/lib/dao/status.rb +4 -0
  38. data/lib/dao/support.rb +155 -0
  39. data/lib/dao/validations.rb +48 -157
  40. data/lib/dao/validations/callback.rb +30 -0
  41. data/lib/dao/validations/common.rb +322 -320
  42. data/lib/dao/validations/validator.rb +219 -0
  43. data/test/active_model_conducer_lint_test.rb +19 -0
  44. data/test/api_test.rb +261 -0
  45. data/test/conducer_test.rb +205 -0
  46. data/test/db.yml +9 -0
  47. data/test/form_test.rb +42 -0
  48. data/test/support_test.rb +52 -0
  49. data/test/testing.rb +145 -24
  50. data/test/validations_test.rb +156 -0
  51. metadata +138 -21
  52. data/TODO +0 -33
  53. data/a.rb +0 -80
  54. data/db/dao.yml +0 -5
  55. data/lib/dao/api/interfaces.rb +0 -306
  56. data/lib/dao/interface.rb +0 -28
  57. data/lib/dao/presenter.rb +0 -129
  58. data/lib/dao/rails/lib/generators/dao/api_generator.rb +0 -3
  59. data/lib/dao/validations/base.rb +0 -68
  60. data/test/dao_test.rb +0 -506
@@ -0,0 +1,79 @@
1
+ <%
2
+
3
+ conducer_class_name = @conducer_name.camelize
4
+ controller_class_name = @controller_name.camelize
5
+
6
+ -%>
7
+ class PostsController < ApplicationController
8
+ Post = PostConducer
9
+
10
+ def index
11
+ @posts = Post.for_index(params)
12
+
13
+ respond_to do |format|
14
+ format.html # index.html.erb
15
+ format.json { render :json => @posts }
16
+ end
17
+ end
18
+
19
+ def show
20
+ @post = Post.for_show(params[:id])
21
+
22
+ respond_to do |format|
23
+ format.html # show.html.erb
24
+ format.json { render :json => @post }
25
+ end
26
+ end
27
+
28
+ def new
29
+ @post = Post.for_new(params)
30
+
31
+ respond_to do |format|
32
+ format.html # new.html.erb
33
+ format.json { render :json => @post }
34
+ end
35
+ end
36
+
37
+ def edit
38
+ @post = Post.find(params[:id])
39
+ end
40
+
41
+ def create
42
+ @post = Post.new(params[:post])
43
+
44
+ respond_to do |format|
45
+ if @post.save
46
+ format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
47
+ format.json { render :json => @post, :status => :created, :location => @post }
48
+ else
49
+ format.html { render :action => "new" }
50
+ format.json { render :json => @post.errors, :status => :unprocessable_entity }
51
+ end
52
+ end
53
+ end
54
+
55
+ def update
56
+ @post = Post.find(params[:id])
57
+
58
+ respond_to do |format|
59
+ if @post.update_attributes(params[:post])
60
+ format.html { redirect_to(@post, :notice => 'Post was successfully updated.') }
61
+ format.json { head :ok }
62
+ else
63
+ format.html { render :action => "edit" }
64
+ format.json { render :json => @post.errors, :status => :unprocessable_entity }
65
+ end
66
+ end
67
+ end
68
+
69
+ def destroy
70
+ @post = Post.find(params[:id])
71
+ @post.destroy
72
+
73
+ respond_to do |format|
74
+ format.html { redirect_to(posts_url) }
75
+ format.json { head :ok }
76
+ end
77
+ end
78
+ end
79
+
@@ -85,20 +85,27 @@ if(!window.Dao){
85
85
 
86
86
  };
87
87
  };
88
+ Dao.Api.modes = ["options", "get", "head", "post", "put", "delete", "trace", "connect"];
89
+ Dao.Api.result = null;
90
+ Dao.Api.results = [];
91
+ Dao.Api.defaults = {};
92
+ Dao.Api.defaults.type = 'get';
93
+ Dao.Api.defaults.url = '/';
88
94
 
89
- // meta-program api.read(..), api.post(...), ...
95
+ // meta-program Dao.Api.get(...), Dao.ajax.post(...)
90
96
  //
91
97
  for(var i = 0; i < Dao.Api.modes.length; i++){
92
98
  (function(){
93
99
  var mode = Dao.Api.modes[i];
94
100
 
95
101
  Dao.Api.prototype[mode] = function(){
102
+ var args = Array.prototype.slice.call(arguments);
96
103
  var api = this;
97
- var previous = api.mode;
98
- api.mode = mode;
99
- var returned = api.call.apply(api, arguments);
100
- api.mode = previous;
101
- return(returned);
104
+ var default_type = Dao.Api.defaults.type;
105
+ Dao.Api.defaults.type = mode.toUpperCase();
106
+ var result = api.apply(api, args);
107
+ Dao.Api.defaults.type = default_type;
108
+ return(result);
102
109
  };
103
110
  })();
104
111
  }
@@ -8,20 +8,84 @@ module DaoHelper
8
8
  end
9
9
  end
10
10
 
11
- def dao(path, params, mode = nil)
12
- unless mode
13
- case request.method
14
- when "GET"
15
- mode = :read
16
- when "PUT", "POST", "DELETE"
17
- mode = :write
11
+ def dao(path, *args, &block)
12
+ options = args.extract_options!.to_options!
13
+
14
+ mode = options[:mode]
15
+
16
+ if mode.blank?
17
+ mode =
18
+ case request.method
19
+ when "GET"
20
+ :read
21
+ when "PUT", "POST", "DELETE"
22
+ :write
23
+ else
24
+ :read
25
+ end
26
+ end
27
+
28
+ @dao = api.send(mode, path, params)
29
+ @dao.route = request.fullpath
30
+ #@dao.mode = mode
31
+
32
+ #unless options[:error!] == false
33
+ @dao.error! unless @dao.status.ok?
34
+ #end
35
+
36
+ block ? block.call(@dao) : @dao
37
+ end
38
+
39
+ def dao_form_for(*args, &block)
40
+ options = args.extract_options!.to_options!
41
+
42
+ model = args.flatten.select{|arg| arg.respond_to?(:new_record?)}.last
43
+
44
+ if model
45
+ first = args.first
46
+ url = options.delete(:url)
47
+ method = options.delete(:method)
48
+ html = dao_form_attrs(options)
49
+
50
+ options.clear
51
+
52
+ if model.new_record?
53
+ url ||= url_for(first)
54
+ method ||= :post
18
55
  else
19
- # do nothing - the user must specificy the mode explicity
56
+ url ||= url_for(first)
57
+ method ||= :put
58
+ end
59
+
60
+ options[:url] = url
61
+ options[:html] = html.dup.merge(:method => method)
62
+
63
+ args.push(options)
64
+
65
+ form_for(*args) do
66
+ block.call(model.form)
20
67
  end
68
+ else
69
+ args.push(request.fullpath) if args.empty?
70
+ args.push(dao_form_attrs(options))
71
+ form_tag(*args, &block)
21
72
  end
22
- result = api.send(mode, path, params)
23
- result.route = request.fullpath
24
- result
25
73
  end
74
+
75
+ def dao_form_attrs(*args)
76
+ args.flatten!
77
+ options = args.extract_options!.to_options!.dup
78
+ options[:class] ||= []
79
+ options[:class] = Array(options[:class])
80
+ options[:class].push('dao')
81
+ options[:class].push(args.map{|arg| arg.to_s})
82
+ options[:class].flatten!
83
+ options[:class].compact!
84
+ options[:class].uniq!
85
+ options[:class] = options[:class].join(' ')
86
+ options[:enctype] ||= "multipart/form-data"
87
+ options
88
+ end
89
+
26
90
  end
27
91
  ApplicationController.send(:include, DaoHelper)
data/lib/dao/result.rb CHANGED
@@ -7,38 +7,13 @@ module Dao
7
7
  self.route = options[:route] || Route.default
8
8
  self.mode = options[:mode] || Mode.default
9
9
  self.status = options[:status] || Status.default
10
- self.errors = options[:errors] || Errors.new
11
10
  self.params = options[:params] || Params.new
11
+ self.errors = options[:errors] || Errors.new
12
12
  self.data = options[:data] || Data.new
13
-
14
- params.result = self
15
- params.path = self.path
16
- params.status = self.status
17
- params.errors = self.errors
18
- end
19
-
20
- def error!
21
- raise Dao::Error::Result.for(self)
22
13
  end
23
14
 
24
- # look good for inspect
25
- #
26
15
  def inspect
27
16
  ::JSON.pretty_generate(self, :max_nesting => 0)
28
17
  end
29
-
30
- # delegate some methods to the params
31
- #
32
- Validations::Mixin.list.each do |method|
33
- module_eval <<-__, __FILE__, __LINE__
34
- def #{ method }(*args)
35
- params.send(#{ method.inspect }, *args)
36
- end
37
- __
38
- end
39
-
40
- def form
41
- params.form
42
- end
43
18
  end
44
19
  end
data/lib/dao/slug.rb CHANGED
@@ -1,11 +1,40 @@
1
- module Dao
2
- class Slug < ::String
3
- def Slug.for(*args)
4
- string = args.flatten.compact.join('-')
5
- words = string.to_s.scan(%r/\w+/)
6
- words.map!{|word| word.gsub(%r/[^0-9a-zA-Z_-]/, '')}
7
- words.delete_if{|word| word.nil? or word.strip.empty?}
8
- new(words.join('-').downcase)
1
+ begin
2
+ require 'rubygems'
3
+ rescue LoadError
4
+ end
5
+
6
+ begin
7
+ require 'unidecode'
8
+ rescue LoadError
9
+ end
10
+
11
+ class Slug < ::String
12
+ Slug::Version = '0.0.1'
13
+
14
+ def Slug.version
15
+ '0.0.1'
16
+ end
17
+
18
+ Join = '-'
19
+
20
+ def Slug.for(*args)
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
22
+ join = options[:join]||options['join']||Join
23
+ string = args.flatten.compact.join(join)
24
+ string = unidecode(string)
25
+ words = string.to_s.scan(%r/\w+/)
26
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
27
+ words.delete_if{|word| word.nil? or word.strip.empty?}
28
+ new(words.join(join).downcase)
29
+ end
30
+
31
+ unless defined?(Unidecoder)
32
+ def Slug.unidecode(string)
33
+ string
34
+ end
35
+ else
36
+ def Slug.unidecode(string)
37
+ Unidecoder.decode(string)
9
38
  end
10
39
  end
11
40
  end
data/lib/dao/status.rb CHANGED
@@ -187,6 +187,10 @@ module Dao
187
187
  end
188
188
  alias_method('set', 'update')
189
189
 
190
+ def ok!
191
+ update(200)
192
+ end
193
+
190
194
  Groups.each do |code, group|
191
195
  module_eval <<-__, __FILE__, __LINE__ -1
192
196
  def Status.#{ group }
data/lib/dao/support.rb CHANGED
@@ -69,4 +69,159 @@ module Dao
69
69
  def parse(*args, &block)
70
70
  Params.process(*args, &block)
71
71
  end
72
+
73
+ def normalize_parameters(params)
74
+ Params.normalize_parameters(params)
75
+ end
76
+
77
+ def current
78
+ @current ||=
79
+ Map.new(
80
+ :controller => nil
81
+ )
82
+ end
83
+
84
+ def current_controller(*args)
85
+ current.controller = args.first unless args.empty?
86
+ current.controller || mock_controller
87
+ end
88
+ alias_method('controller', 'current_controller')
89
+
90
+ def current_controller=(controller)
91
+ current.controller = controller
92
+ end
93
+ alias_method('controller=', 'current_controller=')
94
+
95
+ %w( request response session ).each do |attr|
96
+ module_eval <<-__, __FILE__, __LINE__
97
+ def current_#{ attr }
98
+ @current_#{ attr } ||= current_controller.instance_eval{ #{ attr } }
99
+ end
100
+ def current_#{ attr }=(value)
101
+ @current_#{ attr } = value
102
+ end
103
+ def #{ attr }
104
+ current_#{ attr }
105
+ end
106
+ __
107
+ end
108
+
109
+ %w( current_user effective_user real_user ).each do |attr|
110
+ module_eval <<-__, __FILE__, __LINE__
111
+ def #{ attr }
112
+ @#{ attr } ||= current_controller.instance_eval{ #{ attr } }
113
+ end
114
+ __
115
+ end
116
+
117
+ def root
118
+ if defined?(Rails.root) and Rails.root
119
+ Rails.root
120
+ else
121
+ '.'
122
+ end
123
+ end
124
+
125
+ def key_for(*keys)
126
+ key = keys.flatten.join('.').strip
127
+ key.split(%r/\s*[,.:_-]\s*/).map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
128
+ end
129
+
130
+ def mock_controller
131
+ ensure_rails_application do
132
+ require 'action_dispatch/testing/test_request.rb'
133
+ require 'action_dispatch/testing/test_response.rb'
134
+ store = ActiveSupport::Cache::MemoryStore.new
135
+ controller =
136
+ begin
137
+ ApplicationController.new
138
+ rescue NameError
139
+ ActionController::Base.new
140
+ end
141
+ controller.perform_caching = true
142
+ controller.cache_store = store
143
+ request = ActionDispatch::TestRequest.new
144
+ response = ActionDispatch::TestResponse.new
145
+ controller.request = request
146
+ controller.response = response
147
+ controller.send(:initialize_template_class, response)
148
+ controller.send(:assign_shortcuts, request, response)
149
+ controller.send(:default_url_options).merge!(DefaultUrlOptions) if defined?(DefaultUrlOptions)
150
+ controller
151
+ end
152
+ end
153
+
154
+ def ensure_rails_application(&block)
155
+ if Rails.application.nil?
156
+ mock = Class.new(Rails::Application)
157
+ Rails.application = mock.instance
158
+ begin
159
+ block.call()
160
+ ensure
161
+ Rails.application = nil
162
+ end
163
+ else
164
+ block.call()
165
+ end
166
+ end
167
+
168
+ def normalize_parameters(params)
169
+ dao = (params.delete('dao') || {}).merge(params.delete(:dao) || {})
170
+
171
+ unless dao.blank?
172
+ dao.each do |key, paths_and_values|
173
+ params[key] = nil
174
+ next if paths_and_values.blank?
175
+
176
+ map = Map.new
177
+
178
+ paths_and_values.each do |path, value|
179
+ keys = keys_for(path)
180
+ map.set(keys => value)
181
+ end
182
+
183
+ params[key] = map
184
+ end
185
+ end
186
+
187
+ #params[:dao] = {:normalized => true}
188
+ params
189
+ end
190
+
191
+ def keys_for(keys)
192
+ keys.strip.split(%r/\s*[,._-]\s*/).map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
193
+ end
194
+
195
+ def render_json(object, options = {})
196
+ options = options.to_options!
197
+ controller = options[:controller] || Dao.current_controller
198
+
199
+ controller.instance_eval do
200
+ json = Dao.json_for(object)
201
+
202
+ status = object.status rescue (options[:status] || 200)
203
+ status = status.code if status.respond_to?(:code)
204
+
205
+ respond_to do |wants|
206
+ wants.json{ render :json => json, :status => status }
207
+ wants.html{ render :text => json, :status => status, :content_type => 'text/plain' }
208
+ wants.xml{ render :text => 'no soup for you!', :status => 403 }
209
+ end
210
+ end
211
+ end
212
+
213
+ def json_for(object)
214
+ object = object.as_json if object.respond_to?(:as_json)
215
+
216
+ begin
217
+ if Rails.env.production?
218
+ ::JSON.generate(object)
219
+ else
220
+ ::JSON.pretty_generate(object, :max_nesting => 0)
221
+ end
222
+ rescue Object => e
223
+ Rails.logger.error(e)
224
+ YAML.load( object.to_yaml ).to_json
225
+ end
226
+ end
72
227
  end