dao 4.2.1 → 4.4.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.
Files changed (78) hide show
  1. data/README +103 -63
  2. data/Rakefile +3 -3
  3. data/dao.gemspec +27 -16
  4. data/lib/dao.rb +17 -17
  5. data/lib/dao/active_record.rb +1 -0
  6. data/lib/dao/api.rb +2 -1
  7. data/lib/dao/api/{endpoints.rb → call.rb} +1 -0
  8. data/lib/dao/api/context.rb +2 -0
  9. data/lib/dao/api/dsl.rb +1 -0
  10. data/lib/dao/api/initializers.rb +1 -0
  11. data/lib/dao/api/modes.rb +1 -0
  12. data/lib/dao/api/routes.rb +1 -0
  13. data/lib/dao/blankslate.rb +1 -0
  14. data/lib/dao/conducer.rb +315 -274
  15. data/lib/dao/conducer/active_model.rb +98 -0
  16. data/lib/dao/conducer/attributes.rb +1 -0
  17. data/lib/dao/conducer/autocrud.rb +58 -0
  18. data/lib/dao/conducer/callback_support.rb +20 -0
  19. data/lib/dao/conducer/collection.rb +45 -0
  20. data/lib/dao/conducer/controller_support.rb +104 -0
  21. data/lib/dao/conducer/nav_support.rb +9 -0
  22. data/lib/dao/conducer/view_support.rb +16 -0
  23. data/lib/dao/data.rb +2 -1
  24. data/lib/dao/db.rb +2 -0
  25. data/lib/dao/endpoint.rb +1 -0
  26. data/lib/dao/engine.rb +1 -0
  27. data/lib/dao/errors.rb +109 -99
  28. data/lib/dao/exceptions.rb +1 -0
  29. data/lib/dao/extractor.rb +1 -0
  30. data/lib/dao/form.rb +175 -20
  31. data/lib/dao/instance_exec.rb +1 -0
  32. data/lib/dao/mode.rb +1 -0
  33. data/lib/dao/mongo_mapper.rb +1 -0
  34. data/lib/dao/name.rb +1 -0
  35. data/lib/dao/params.rb +2 -1
  36. data/lib/dao/path.rb +1 -0
  37. data/lib/dao/path_map.rb +24 -0
  38. data/lib/dao/rack.rb +1 -0
  39. data/lib/dao/rack/middleware.rb +1 -0
  40. data/lib/dao/rack/middleware/params_parser.rb +1 -0
  41. data/lib/dao/rails.rb +12 -32
  42. data/lib/dao/rails/lib/generators/dao/USAGE +2 -2
  43. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +8 -27
  44. data/lib/dao/rails/lib/generators/dao/templates/api.rb +2 -1
  45. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +22 -20
  46. data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +49 -43
  47. data/lib/dao/rails/lib/generators/dao/templates/dao.css +26 -25
  48. data/lib/dao/rails/lib/generators/dao/templates/dao.js +3 -0
  49. data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +58 -45
  50. data/lib/dao/result.rb +50 -1
  51. data/lib/dao/route.rb +1 -0
  52. data/lib/dao/slug.rb +12 -36
  53. data/lib/dao/status.rb +91 -7
  54. data/lib/dao/stdext.rb +1 -0
  55. data/lib/dao/support.rb +90 -80
  56. data/lib/dao/upload.rb +396 -0
  57. data/lib/dao/validations.rb +23 -5
  58. data/lib/dao/validations/callback.rb +5 -0
  59. data/lib/dao/validations/common.rb +100 -3
  60. data/lib/dao/validations/instance.rb +17 -0
  61. data/lib/dao/validations/validator.rb +192 -91
  62. data/test/active_model_conducer_lint_test.rb +1 -0
  63. data/test/api_test.rb +15 -0
  64. data/test/conducer_test.rb +608 -90
  65. data/test/data/han-solo.jpg +0 -0
  66. data/test/form_test.rb +1 -0
  67. data/test/helper.rb +1 -0
  68. data/test/leak.rb +1 -0
  69. data/test/support_test.rb +4 -1
  70. data/test/testing.rb +1 -0
  71. data/test/validations_test.rb +176 -30
  72. metadata +120 -131
  73. data/b.rb +0 -38
  74. data/lib/dao/conducer/crud.rb +0 -70
  75. data/lib/dao/current.rb +0 -66
  76. data/lib/dao/image_cache.rb +0 -193
  77. data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +0 -79
  78. data/test/db.yml +0 -9
@@ -1,5 +1,5 @@
1
1
  Description:
2
- rails generate dao system
2
+ rails generate dao system|conducer
3
3
 
4
4
  Example:
5
- rails generate dao system
5
+ rails generate dao system|conducer
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  class DaoGenerator < Rails::Generators::NamedBase
2
3
  source_root(File.expand_path('../templates', __FILE__))
3
4
 
@@ -5,9 +6,6 @@ class DaoGenerator < Rails::Generators::NamedBase
5
6
  ARGV.shift if ARGV.first == name
6
7
 
7
8
  case name
8
- when /conducer_controller/
9
- generate_conducer_controller!
10
-
11
9
  when /conducer/
12
10
  generate_conducer!
13
11
 
@@ -17,9 +15,6 @@ class DaoGenerator < Rails::Generators::NamedBase
17
15
  when /api/
18
16
  generate_system!
19
17
 
20
- when /conducers/
21
- generate_system!
22
-
23
18
  when /assets/
24
19
  generate_system!
25
20
 
@@ -29,13 +24,6 @@ class DaoGenerator < Rails::Generators::NamedBase
29
24
  end
30
25
 
31
26
  protected
32
- def generate_conducer_controller!
33
- @conducer_name = ARGV.shift.sub(/_?conducer$/i, '') + '_conducer'
34
- @controller_name = @conducer_name.sub(/_conducer/, '_controller')
35
-
36
- template "conducer_controller.rb", "app/controllers/#{ @conducer_name.underscore }.rb"
37
- #template "conducer.rb", "app/conducers/#{ @conducer_name.underscore }.rb"
38
- end
39
27
 
40
28
  def generate_conducer!
41
29
  @conducer_name = ARGV.shift.sub(/_?conducer$/i, '') + '_conducer'
@@ -43,34 +31,27 @@ protected
43
31
  end
44
32
 
45
33
  def generate_system!
46
- dao_dir = File.join(Rails.root, 'app/dao')
34
+ FileUtils.mkdir_p(File.join(Rails.root, 'app/conducers'))
47
35
 
48
- FileUtils.mkdir_p(dao_dir)
49
- FileUtils.mkdir_p(File.join(dao_dir, 'apis'))
50
- FileUtils.mkdir_p(File.join(dao_dir, 'conducers'))
51
-
52
- copy_file("api.rb", "app/dao/api.rb")
36
+ copy_file("api.rb", "lib/api.rb")
53
37
 
54
38
  copy_file("api_controller.rb", "app/controllers/api_controller.rb")
39
+
55
40
  copy_file("dao_helper.rb", "app/helpers/dao_helper.rb")
56
41
 
57
- copy_file("dao.js", "public/javascripts/dao.js")
58
- copy_file("dao.css", "public/stylesheets/dao.css")
42
+ copy_file("dao.js", "app/assets/javascripts/dao.js")
59
43
 
60
- route("match 'api(/*path)' => 'api#index', :as => 'api'")
44
+ copy_file("dao.css", "app/assets/stylesheets/dao.css")
61
45
 
62
- gem("yajl-ruby")
46
+ route("match 'api(/*path)' => 'api#index', :as => 'api'")
63
47
 
64
48
  application(
65
49
  <<-__
66
50
 
67
51
  config.after_initialize do
68
- require 'app/dao/api.rb'
69
- require 'yajl/json_gem'
52
+ require File.join(Rails.root, 'lib/api.rb')
70
53
  end
71
54
 
72
- config.autoload_paths += %w( app/models app/dao app/dao/apis app/dao/conducers )
73
-
74
55
  ### config.action_view.javascript_expansions[:defaults] ||= []
75
56
  ### config.action_view.javascript_expansions[:defaults] += %( dao )
76
57
 
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  Api =
2
3
  Dao.api do
3
4
  ##
@@ -21,7 +22,7 @@ Api =
21
22
  call('/pong'){
22
23
  require_current_user!
23
24
  data.update :time => Time.now
24
- data.update :current_user => current_user.id
25
+ data.update :current_user => current_user
25
26
  }
26
27
 
27
28
  ## this is simply a suggested way to model your api. it is not required.
@@ -1,4 +1,9 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ Kernel.load(File.join(Rails.root, 'lib/api.rb'))
4
+
1
5
  class APIController < ApplicationController
6
+
2
7
  layout false
3
8
 
4
9
  skip_before_filter :verify_authenticity_token
@@ -22,38 +27,35 @@ protected
22
27
  end
23
28
 
24
29
  def respond_with(object, options = {})
25
- json = json_for(object)
30
+ json = Dao.json_for(object)
26
31
 
27
32
  status = object.status rescue (options[:status] || 200)
28
33
  status = status.code if status.respond_to?(:code)
29
34
 
30
- respond_to do |wants|
31
- wants.json{ render :json => json, :status => status }
32
- wants.html{ render :text => json, :status => status, :content_type => 'text/plain' }
33
- wants.xml{ render :text => 'no soup for you!', :status => 403 }
34
- end
35
- end
36
-
37
- def json_for(object)
38
- begin
39
- if Rails.env.production?
40
- ::JSON.generate(object)
41
- else
42
- ::JSON.pretty_generate(object, :max_nesting => 0)
35
+ if @format == 'json'
36
+ render(:json => json, :status => status)
37
+ else
38
+ respond_to do |wants|
39
+ wants.json{ render :json => json, :status => status }
40
+ wants.html{ render :text => json, :status => status, :content_type => 'text/plain' }
41
+ wants.xml{ render :text => 'no soup for you!', :status => 403 }
43
42
  end
44
- rescue Object => e
45
- Rails.logger.error(e)
46
- YAML.load( object.to_yaml ).to_json
47
43
  end
48
44
  end
49
45
 
50
46
  def setup_path
51
47
  @path = params[:path] || params[:action] || 'index'
52
- unless api.route?(@path) or @path=='index'
48
+ @path, @format = @path.split(/\./, 2)
49
+ unless @format.blank?
50
+ params[:format] = @format
51
+ params[:path] = @path
52
+ end
53
+ unless api.route?(@path) or @path == 'index'
53
54
  render :nothing => true, :status => 404
54
55
  end
55
56
  end
56
57
 
58
+
57
59
  def setup_mode
58
60
  @mode = params['mode'] || (request.get? ? 'read' : 'write')
59
61
  end
@@ -87,13 +89,13 @@ protected
87
89
  return
88
90
  end
89
91
  else
90
- if defined?(current_user)
92
+ begin
91
93
  if current_user
92
94
  @api = Api.new(current_user)
93
95
  else
94
96
  render(:nothing => true, :status => :unauthorized)
95
97
  end
96
- else
98
+ rescue NameError
97
99
  @api = Api.new
98
100
  end
99
101
  end
@@ -1,64 +1,70 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  <%
2
3
 
3
4
  class_name = @conducer_name.camelize
4
5
  model_name = class_name.sub(/Conducer/, '')
5
6
 
6
7
  -%>
8
+
7
9
  class <%= class_name %> < Dao::Conducer
8
- ## class_methods
9
- #
10
- class << <%= class_name %>
11
- def all(params = {})
12
- records = <%= model_name %>.paginate(params)
13
-
14
- records.map! do |record|
15
- new(record.attributes)
16
- end
17
- end
10
+ def initialize(user, model, params = {})
11
+ @user = user
12
+ @model = model
18
13
 
19
- def find(id)
20
- raise NotImplementedError, <<-__
21
- this needs to return an instance based on the id
22
- __
23
- end
24
- end
14
+ update_attributes(
15
+ :user => @user.attributes,
16
+ :model => @model.attributes,
17
+
18
+ :foo => 'bar'
19
+ )
20
+
21
+ id!(@model.id) unless @model.new_record?
22
+
23
+ mount(Dao::Upload, :logo, :placeholder => (@model.logo.try(:url) || 'http://placeholder.com/image.png'))
24
+
25
+ case action
26
+ when 'new', 'create'
27
+ @attributes.email = @user.email
28
+ @model.field = @page.field
29
+
30
+ update_attributes(params)
31
+
32
+ when 'edit', 'update', 'show'
33
+ @attributes.email = @user.email
34
+ @model.field = @page.field
25
35
 
26
- ## instance_methods
27
- #
28
- def initialize
29
- run_callbacks :initialize do
36
+ update_attributes(params)
30
37
  end
31
38
  end
32
39
 
40
+
41
+ validates_presence_of :something
42
+
33
43
  def save
34
- run_callbacks :save do
35
- return(false) unless valid?
44
+ return(false) unless valid?
36
45
 
37
- raise NotImplementedError, <<-__
38
- this needs to
39
- - persist data to the db and get a new id
40
- - set the id on the object : @attributes.set(:id => id)
41
- - return true or false
42
- __
46
+ raise NotImplementedError, <<-__
47
+ this needs to
48
+ - persist data to the db and get a new id
49
+ - set the id on the object : @attributes.set(:id => id)
50
+ - return true or false
51
+ __
43
52
 
44
- true
45
- end
53
+ true
46
54
  end
47
55
 
48
56
  def destroy
49
- run_callbacks :destroy do
50
- id = self.id
51
- if id
52
-
53
- raise NotImplementedError, <<-__
54
- this needs to
55
- - un-persist data from the db
56
- - set the id on the object to nil : @attributes.rm(:id)
57
- - return this id of the destroyed object
58
- __
59
-
60
- end
61
- id
57
+ id = self.id
58
+ if id
59
+
60
+ raise NotImplementedError, <<-__
61
+ this needs to
62
+ - un-persist data from the db
63
+ - set the id on the object to nil : @attributes.rm(:id)
64
+ - return this id of the destroyed object
65
+ __
66
+
62
67
  end
68
+ id
63
69
  end
64
70
  end
@@ -1,27 +1,28 @@
1
1
  /* dao errors */
2
- table.dao.errors {
3
- font-weight: normal;
4
- width: 100%;
5
- border-bottom: 1px solid #ccc;
6
- }
7
- table.dao.errors caption {
8
- font-weight: bold;
9
- color: #333;
10
- font-style: italic;
11
- text-align: left;
12
- margin-bottom: 0.5em;
13
- }
14
- table.dao.errors td.key {
15
- padding-left: 1em;
16
- color: #666;
17
- }
18
- table.dao.errors td.separator {
19
- color: #666;
20
- padding-left: 0.5em;
21
- padding-right: 0.5em;
22
- }
23
- table.dao.errors td.message {
24
- font-style: italic;
25
- width: 100%;
26
- }
27
2
 
3
+ .dao.errors {
4
+ font-weight: normal;
5
+ width: 100%;
6
+ border-bottom: 1px solid #ccc;
7
+ background-color: #ffe;
8
+ padding: 0.5em;
9
+ }
10
+
11
+ .dao.errors .caption {
12
+ font-weight: bold;
13
+ color: #333;
14
+ font-style: italic;
15
+ text-align: left;
16
+ margin-bottom: 0.5em;
17
+ }
18
+
19
+ .dao.errors .title {
20
+ padding-left: 1em;
21
+ color: #666;
22
+ }
23
+
24
+ .dao.errors .message {
25
+ font-style: italic;
26
+ font-weight: bold;
27
+ width: 100%;
28
+ }
@@ -109,6 +109,9 @@ if(!window.Dao){
109
109
  };
110
110
  })();
111
111
  }
112
+
113
+ // short-cuts for read and write
114
+ //
112
115
  Dao.Api.prototype['read'] = Dao.Api.prototype['get'];
113
116
  Dao.Api.prototype['write'] = Dao.Api.prototype['post'];
114
117
 
@@ -1,65 +1,40 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module DaoHelper
2
- def render_dao(result, *args, &block)
3
- if result.status =~ 200 or result.status == 420
4
- @result = result unless defined?(@result)
5
- render(*args, &block)
6
- else
7
- result.error!
8
- end
9
- end
10
-
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
3
  def dao_form_for(*args, &block)
40
4
  options = args.extract_options!.to_options!
41
5
 
42
- model = args.flatten.select{|arg| arg.respond_to?(:new_record?)}.last
6
+ model = args.flatten.detect{|arg| arg.respond_to?(:persisted?)}
43
7
 
44
8
  if model
45
- first = args.first
46
- url = options.delete(:url)
9
+ first = args.shift
10
+ url = args.shift || options.delete(:url)
11
+
47
12
  method = options.delete(:method)
48
13
  html = dao_form_attrs(options)
49
14
 
50
15
  options.clear
51
16
 
52
- if model.new_record?
53
- url ||= url_for(first)
54
- method ||= :post
55
- else
56
- url ||= url_for(first)
17
+ if model.persisted?
57
18
  method ||= :put
19
+ else
20
+ method ||= :post
58
21
  end
59
22
 
23
+ url =
24
+ case method
25
+ when :put
26
+ url_for(:action => :update)
27
+ when :post
28
+ url_for(:action => :create)
29
+ else
30
+ './'
31
+ end
32
+
60
33
  options[:url] = url
61
34
  options[:html] = html.dup.merge(:method => method)
35
+ #options[:builder] = Dao::Form::Builder
62
36
 
37
+ args.push(model)
63
38
  args.push(options)
64
39
 
65
40
  form_for(*args) do
@@ -72,6 +47,8 @@ module DaoHelper
72
47
  end
73
48
  end
74
49
 
50
+ alias_method(:dao_form, :dao_form_for)
51
+
75
52
  def dao_form_attrs(*args)
76
53
  args.flatten!
77
54
  options = args.extract_options!.to_options!.dup
@@ -87,5 +64,41 @@ module DaoHelper
87
64
  options
88
65
  end
89
66
 
67
+ def render_dao(result, *args, &block)
68
+ if result.status =~ 200 or result.status == 420
69
+ @result = result unless defined?(@result)
70
+ render(*args, &block)
71
+ else
72
+ result.error!
73
+ end
74
+ end
75
+
76
+ def dao(path, *args, &block)
77
+ options = args.extract_options!.to_options!
78
+
79
+ mode = options[:mode]
80
+
81
+ if mode.blank?
82
+ mode =
83
+ case request.method
84
+ when "GET"
85
+ :read
86
+ when "PUT", "POST", "DELETE"
87
+ :write
88
+ else
89
+ :read
90
+ end
91
+ end
92
+
93
+ @dao = api.send(mode, path, params)
94
+ @dao.route = request.fullpath
95
+ #@dao.mode = mode
96
+
97
+ #unless options[:error!] == false
98
+ @dao.error! unless @dao.status.ok?
99
+ #end
100
+
101
+ block ? block.call(@dao) : @dao
102
+ end
90
103
  end
91
104
  ApplicationController.send(:include, DaoHelper)