dao 0.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/README +35 -0
  2. data/Rakefile +6 -3
  3. data/TODO +37 -0
  4. data/dao.gemspec +30 -0
  5. data/db/dao.yml +8 -0
  6. data/lib/dao.rb +84 -5
  7. data/lib/dao/active_record.rb +76 -0
  8. data/lib/dao/api.rb +9 -0
  9. data/lib/dao/api/context.rb +38 -0
  10. data/lib/dao/api/dsl.rb +50 -0
  11. data/lib/dao/api/endpoints.rb +190 -0
  12. data/lib/dao/api/initializers.rb +71 -0
  13. data/lib/dao/api/modes.rb +85 -0
  14. data/lib/dao/blankslate.rb +5 -0
  15. data/lib/dao/data.rb +58 -0
  16. data/lib/dao/db.rb +183 -0
  17. data/lib/dao/endpoint.rb +16 -0
  18. data/lib/dao/engine.rb +7 -0
  19. data/lib/dao/errors.rb +238 -0
  20. data/lib/dao/exceptions.rb +2 -0
  21. data/lib/dao/form.rb +236 -0
  22. data/lib/dao/mode.rb +41 -0
  23. data/lib/dao/mongo_mapper.rb +70 -0
  24. data/lib/dao/params.rb +109 -0
  25. data/lib/dao/path.rb +149 -0
  26. data/lib/dao/rails.rb +15 -0
  27. data/lib/dao/rails/app/api.rb +55 -0
  28. data/lib/dao/rails/app/controllers/api_controller.rb +99 -0
  29. data/lib/dao/rails/lib/generators/dao/USAGE +9 -0
  30. data/lib/dao/rails/lib/generators/dao/api_generator.rb +3 -0
  31. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +27 -0
  32. data/lib/dao/rails/lib/generators/dao/templates/api.rb +55 -0
  33. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +99 -0
  34. data/lib/dao/result.rb +87 -0
  35. data/lib/dao/slug.rb +11 -0
  36. data/lib/dao/status.rb +223 -0
  37. data/lib/dao/stdext.rb +10 -0
  38. data/lib/dao/support.rb +62 -0
  39. data/lib/dao/validations.rb +115 -0
  40. data/sample/rails_app/Gemfile +33 -0
  41. data/sample/rails_app/Gemfile.lock +88 -0
  42. data/sample/rails_app/README +1 -0
  43. data/sample/rails_app/Rakefile +7 -0
  44. data/sample/rails_app/app/api.rb +55 -0
  45. data/sample/rails_app/app/controllers/api_controller.rb +99 -0
  46. data/sample/rails_app/app/controllers/application_controller.rb +3 -0
  47. data/sample/rails_app/app/helpers/application_helper.rb +2 -0
  48. data/sample/rails_app/app/views/layouts/application.html.erb +14 -0
  49. data/sample/rails_app/config.ru +4 -0
  50. data/sample/rails_app/config/application.rb +51 -0
  51. data/sample/rails_app/config/boot.rb +13 -0
  52. data/sample/rails_app/config/database.yml +22 -0
  53. data/sample/rails_app/config/environment.rb +5 -0
  54. data/sample/rails_app/config/environments/development.rb +26 -0
  55. data/sample/rails_app/config/environments/production.rb +49 -0
  56. data/sample/rails_app/config/environments/test.rb +35 -0
  57. data/sample/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  58. data/sample/rails_app/config/initializers/inflections.rb +10 -0
  59. data/sample/rails_app/config/initializers/mime_types.rb +5 -0
  60. data/sample/rails_app/config/initializers/secret_token.rb +7 -0
  61. data/sample/rails_app/config/initializers/session_store.rb +8 -0
  62. data/sample/rails_app/config/locales/en.yml +5 -0
  63. data/sample/rails_app/config/routes.rb +62 -0
  64. data/sample/rails_app/db/development.sqlite3 +0 -0
  65. data/sample/rails_app/db/seeds.rb +7 -0
  66. data/sample/rails_app/doc/README_FOR_APP +2 -0
  67. data/sample/rails_app/log/development.log +27 -0
  68. data/sample/rails_app/log/production.log +0 -0
  69. data/sample/rails_app/log/server.log +0 -0
  70. data/sample/rails_app/log/test.log +0 -0
  71. data/sample/rails_app/public/404.html +26 -0
  72. data/sample/rails_app/public/422.html +26 -0
  73. data/sample/rails_app/public/500.html +26 -0
  74. data/sample/rails_app/public/favicon.ico +0 -0
  75. data/sample/rails_app/public/images/rails.png +0 -0
  76. data/sample/rails_app/public/index.html +239 -0
  77. data/sample/rails_app/public/javascripts/application.js +2 -0
  78. data/sample/rails_app/public/javascripts/controls.js +965 -0
  79. data/sample/rails_app/public/javascripts/dragdrop.js +974 -0
  80. data/sample/rails_app/public/javascripts/effects.js +1123 -0
  81. data/sample/rails_app/public/javascripts/prototype.js +6001 -0
  82. data/sample/rails_app/public/javascripts/rails.js +175 -0
  83. data/sample/rails_app/public/robots.txt +5 -0
  84. data/sample/rails_app/script/rails +6 -0
  85. data/sample/rails_app/test/performance/browsing_test.rb +9 -0
  86. data/sample/rails_app/test/test_helper.rb +13 -0
  87. data/test/dao_test.rb +271 -0
  88. data/test/helper.rb +15 -0
  89. data/test/testing.rb +74 -0
  90. metadata +137 -9
data/lib/dao/path.rb ADDED
@@ -0,0 +1,149 @@
1
+ module Dao
2
+ class Path < ::String
3
+ class Error < ::StandardError; end
4
+ class Error::Params < Error; end
5
+
6
+ class << Path
7
+ def for(*args)
8
+ new(absolute_path_for(*args))
9
+ end
10
+
11
+ def paths_for(arg, *args)
12
+ path = [arg, *args].flatten.compact.join('/')
13
+ path.gsub!(%r|[.]+/|, '/')
14
+ path.squeeze!('/')
15
+ path.sub!(%r|^/|, '')
16
+ path.sub!(%r|/$|, '')
17
+ paths = path.split('/')
18
+ end
19
+
20
+ def absolute_path_for(arg, *args)
21
+ ('/' + paths_for(arg, *args).join('/')).squeeze('/')
22
+ end
23
+
24
+ def cast(*args)
25
+ if args.size == 1
26
+ value = args.first
27
+ value.is_a?(self) ? value : self.for(value)
28
+ else
29
+ self.for(*args)
30
+ end
31
+ end
32
+
33
+ def params?(string)
34
+ string.to_s =~ %r{/:[^/]+}
35
+ end
36
+ alias_method('=~', 'params?')
37
+
38
+ def absolute?(string)
39
+ string.to_s =~ %r|^\s*/|
40
+ end
41
+
42
+ def keys_for(path)
43
+ path = absolute_path_for(path)
44
+ path.scan(%r{/:[^/]+}).map{|key| key.sub(%r{^/:}, '')}
45
+ end
46
+
47
+ def expand!(path, params = {})
48
+ params = Map.for(params)
49
+ path.keys.each do |key|
50
+ path.gsub!(%r{/:#{ Regexp.escape(key) }\b}, params[key])
51
+ end
52
+ path
53
+ end
54
+
55
+ def pattern_for(path)
56
+ path = absolute_path_for(path)
57
+ re = path.gsub(%r{/:[^/]+}, '/([^/]+)')
58
+ /^#{ re }$/i
59
+ end
60
+
61
+ def extract_params(enumerable, keys)
62
+ params = Map.new
63
+ keys = Array(keys)
64
+ case enumerable
65
+ when Array
66
+ keys.each_with_index{|key, index| params[key] = enumerable[index]}
67
+ when Hash
68
+ enumerable = Map.for(enumerable)
69
+ keys.each{|key| params[key] = enumerable[key]}
70
+ else
71
+ raise(ArgumentError, enumerable.class.name)
72
+ end
73
+ params
74
+ end
75
+ end
76
+
77
+ attr_accessor :result
78
+ attr_accessor :keys
79
+ attr_accessor :pattern
80
+ attr_accessor :params
81
+ attr_accessor :endpoint
82
+
83
+ def initialize(*args, &block)
84
+ super(args.join('/'), &block)
85
+ normalize!
86
+ compile!
87
+ end
88
+
89
+ def params?
90
+ Path.params?(self)
91
+ end
92
+
93
+ def normalize!
94
+ replace(Path.absolute_path_for(self))
95
+ end
96
+
97
+ def compile!
98
+ @keys = Path.keys_for(self)
99
+ @pattern = Path.pattern_for(self)
100
+ @params = Map.new
101
+ @path = dup
102
+ end
103
+
104
+ def expand(params)
105
+ dup.expand!(params)
106
+ end
107
+
108
+ class ParamsError < ::StandardError; end
109
+
110
+ def expand!(params)
111
+ replace(@path.dup)
112
+ @params = extract_params(params)
113
+ keys.each do |key|
114
+ next if @params[key].nil?
115
+ re = %r{/:#{ Regexp.escape(key) }\b}
116
+ val = "/#{ @params[key] }"
117
+ self.gsub!(re, val)
118
+ end
119
+ raise(Error::Params, "#{ self }(#{ @params.inspect })") if params?
120
+ self
121
+ end
122
+
123
+ def absolute?
124
+ Path.absolute?(self)
125
+ end
126
+
127
+ def match(other)
128
+ matched, *matches = @pattern.match(other).to_a
129
+ matched ? expand(matches) : false
130
+ end
131
+
132
+ def match!(other)
133
+ matched, *matches = @pattern.match(other).to_a
134
+ matched ? expand!(matches) : false
135
+ end
136
+
137
+ def extract_params(enumerable)
138
+ Path.extract_params(enumerable, @keys)
139
+ end
140
+
141
+ def +(other)
142
+ Path.for(super)
143
+ end
144
+
145
+ def to_yaml(*args, &block)
146
+ "#{ self }".to_yaml(*args, &block)
147
+ end
148
+ end
149
+ end
data/lib/dao/rails.rb ADDED
@@ -0,0 +1,15 @@
1
+ if defined?(Rails)
2
+ module Dao
3
+ class Engine < Rails::Engine
4
+ GEM_DIR = File.expand_path(__FILE__ + '/../../../')
5
+ ROOT_DIR = File.join(GEM_DIR, 'lib/dao/rails')
6
+ #APP_DIR = File.join(ROOT_DIR, 'app')
7
+
8
+ ### https://gist.github.com/af7e572c2dc973add221
9
+
10
+ paths.path = ROOT_DIR
11
+ ### config.autoload_paths << APP_DIR
12
+ ### $LOAD_PATH.push(File.join(Rails.root.to_s, 'app'))
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ Api =
2
+ Dao.api do
3
+
4
+ description 'ping!'
5
+ endpoint('/ping'){
6
+ data.update :time => Time.now
7
+ }
8
+
9
+
10
+
11
+
12
+ ## this is simply a suggest way to model your api. it is not required.
13
+ #
14
+ attr_accessor :effective_user
15
+ attr_accessor :real_user
16
+
17
+ def initialize(*args)
18
+ options = args.extract_options!.to_options!
19
+ effective_user = args.shift || options[:effective_user] || options[:user]
20
+ real_user = args.shift || options[:real_user] || effective_user
21
+ @effective_user = user_for(effective_user) if effective_user
22
+ @real_user = user_for(real_user) if real_user
23
+ @real_user ||= @effective_user
24
+ end
25
+
26
+ def user_for(arg)
27
+ User.find(arg)
28
+ end
29
+
30
+ alias_method('user', 'effective_user')
31
+ alias_method('user=', 'effective_user=')
32
+
33
+ def api
34
+ self
35
+ end
36
+
37
+ def logged_in?
38
+ @effective_user and @real_user
39
+ end
40
+
41
+ def user?
42
+ logged_in?
43
+ end
44
+
45
+ def current_user
46
+ effective_user
47
+ end
48
+
49
+ def current_user?
50
+ !!effective_user
51
+ end
52
+ end
53
+
54
+
55
+ unloadable(Api)
@@ -0,0 +1,99 @@
1
+ class APIController < ApplicationController
2
+ layout false
3
+
4
+ skip_before_filter true
5
+ skip_before_filter :verify_authenticity_token
6
+
7
+ before_filter :setup_api
8
+
9
+ ### skip_before_filter :set_current_user if Rails.env.production?
10
+
11
+ ##
12
+ # /api/foo/2/bar/4 -> api.call('/foo/2/bar/4')
13
+ #
14
+ def call
15
+ path = params[:path]
16
+ mode = params['mode'] || (request.get? ? 'read' : 'write')
17
+
18
+ result = api.mode(mode).call(path, params)
19
+
20
+ respond_with(result)
21
+ end
22
+
23
+ ##
24
+ #
25
+ def index
26
+ json = json_for(api.index)
27
+
28
+ respond_to do |wants|
29
+ wants.json{ render(:json => json) }
30
+ wants.html{ render(:text => json, :content_type => 'text/plain') }
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def respond_with(result)
37
+ json = json_for(result)
38
+
39
+ respond_to do |wants|
40
+ wants.json{ render :json => json, :status => result.status.code }
41
+ wants.html{ render :text => json, :status => result.status.code, :content_type => 'text/plain' }
42
+ end
43
+ end
44
+
45
+ # if you don't have yajl-ruby and yajl/json_gem loaded your json will suck
46
+ #
47
+ def json_for(object)
48
+ if Rails.env.production?
49
+ ::JSON.generate(object)
50
+ else
51
+ ::JSON.pretty_generate(object, :max_nesting => 0)
52
+ end
53
+ end
54
+
55
+ def setup_api
56
+ email, password = http_basic_auth_info
57
+
58
+ if !email.blank? and !password.blank?
59
+ user = User.find_by_email(email)
60
+ if user.password == password
61
+ @api = Api.new(user)
62
+ else
63
+ render(:nothing => true, :status => :unauthorized)
64
+ return
65
+ end
66
+ else
67
+ if defined?(current_user)
68
+ if current_user
69
+ @api = Api.new(current_user)
70
+ else
71
+ render(:nothing => true, :status => :unauthorized)
72
+ end
73
+ else
74
+ @api = Api.new
75
+ end
76
+ end
77
+ end
78
+
79
+ def api
80
+ @api
81
+ end
82
+
83
+ def http_basic_auth
84
+ @http_basic_auth ||= (
85
+ request.env['HTTP_AUTHORIZATION'] ||
86
+ request.env['X-HTTP_AUTHORIZATION'] ||
87
+ request.env['X_HTTP_AUTHORIZATION'] ||
88
+ request.env['REDIRECT_X_HTTP_AUTHORIZATION'] ||
89
+ ''
90
+ )
91
+ end
92
+
93
+ def http_basic_auth_info
94
+ username, password =
95
+ ActiveSupport::Base64.decode64(http_basic_auth.split.last.to_s).split(/:/, 2)
96
+ end
97
+ end
98
+
99
+ ApiController = APIController ### rails is a bitch - shut her up
@@ -0,0 +1,9 @@
1
+ Description:
2
+ rails generate dao api
3
+ rails generate dao api controller
4
+ rails generate dao paths
5
+
6
+ Example:
7
+ rails generate dao api
8
+ rails generate dao api controller
9
+ rails generate dao paths
@@ -0,0 +1,3 @@
1
+ class ApiGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+ end
@@ -0,0 +1,27 @@
1
+ class DaoGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def copy_api_file
5
+ copy_file("api.rb", "app/api.rb")
6
+
7
+ copy_file("api_controller.rb", "app/controllers/api_controller.rb")
8
+
9
+ route("match 'api/*path' => 'api#call', :as => 'api'")
10
+ route("match 'api' => 'api#index', :as => 'api_index'")
11
+
12
+ gem("yajl-ruby")
13
+
14
+ application(
15
+ <<-__
16
+
17
+ config.after_initialize do
18
+ require 'app/api.rb'
19
+ require 'yajl/json_gem'
20
+ end
21
+
22
+ config.autoload_paths += %w( app )
23
+
24
+ __
25
+ )
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ Api =
2
+ Dao.api do
3
+
4
+ description 'ping!'
5
+ endpoint('/ping'){
6
+ data.update :time => Time.now
7
+ }
8
+
9
+
10
+
11
+
12
+ ## this is simply a suggest way to model your api. it is not required.
13
+ #
14
+ attr_accessor :effective_user
15
+ attr_accessor :real_user
16
+
17
+ def initialize(*args)
18
+ options = args.extract_options!.to_options!
19
+ effective_user = args.shift || options[:effective_user] || options[:user]
20
+ real_user = args.shift || options[:real_user] || effective_user
21
+ @effective_user = user_for(effective_user) if effective_user
22
+ @real_user = user_for(real_user) if real_user
23
+ @real_user ||= @effective_user
24
+ end
25
+
26
+ def user_for(arg)
27
+ User.find(arg)
28
+ end
29
+
30
+ alias_method('user', 'effective_user')
31
+ alias_method('user=', 'effective_user=')
32
+
33
+ def api
34
+ self
35
+ end
36
+
37
+ def logged_in?
38
+ @effective_user and @real_user
39
+ end
40
+
41
+ def user?
42
+ logged_in?
43
+ end
44
+
45
+ def current_user
46
+ effective_user
47
+ end
48
+
49
+ def current_user?
50
+ !!effective_user
51
+ end
52
+ end
53
+
54
+
55
+ unloadable(Api)
@@ -0,0 +1,99 @@
1
+ class APIController < ApplicationController
2
+ layout false
3
+
4
+ skip_before_filter true
5
+ skip_before_filter :verify_authenticity_token
6
+
7
+ before_filter :setup_api
8
+
9
+ ### skip_before_filter :set_current_user if Rails.env.production?
10
+
11
+ ##
12
+ # /api/foo/2/bar/4 -> api.call('/foo/2/bar/4')
13
+ #
14
+ def call
15
+ path = params[:path]
16
+ mode = params['mode'] || (request.get? ? 'read' : 'write')
17
+
18
+ result = api.mode(mode).call(path, params)
19
+
20
+ respond_with(result)
21
+ end
22
+
23
+ ##
24
+ #
25
+ def index
26
+ json = json_for(api.index)
27
+
28
+ respond_to do |wants|
29
+ wants.json{ render(:json => json) }
30
+ wants.html{ render(:text => json, :content_type => 'text/plain') }
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def respond_with(result)
37
+ json = json_for(result)
38
+
39
+ respond_to do |wants|
40
+ wants.json{ render :json => json, :status => result.status.code }
41
+ wants.html{ render :text => json, :status => result.status.code, :content_type => 'text/plain' }
42
+ end
43
+ end
44
+
45
+ # if you don't have yajl-ruby and yajl/json_gem loaded your json will suck
46
+ #
47
+ def json_for(object)
48
+ if Rails.env.production?
49
+ ::JSON.generate(object)
50
+ else
51
+ ::JSON.pretty_generate(object, :max_nesting => 0)
52
+ end
53
+ end
54
+
55
+ def setup_api
56
+ email, password = http_basic_auth_info
57
+
58
+ if !email.blank? and !password.blank?
59
+ user = User.find_by_email(email)
60
+ if user.password == password
61
+ @api = Api.new(user)
62
+ else
63
+ render(:nothing => true, :status => :unauthorized)
64
+ return
65
+ end
66
+ else
67
+ if defined?(current_user)
68
+ if current_user
69
+ @api = Api.new(current_user)
70
+ else
71
+ render(:nothing => true, :status => :unauthorized)
72
+ end
73
+ else
74
+ @api = Api.new
75
+ end
76
+ end
77
+ end
78
+
79
+ def api
80
+ @api
81
+ end
82
+
83
+ def http_basic_auth
84
+ @http_basic_auth ||= (
85
+ request.env['HTTP_AUTHORIZATION'] ||
86
+ request.env['X-HTTP_AUTHORIZATION'] ||
87
+ request.env['X_HTTP_AUTHORIZATION'] ||
88
+ request.env['REDIRECT_X_HTTP_AUTHORIZATION'] ||
89
+ ''
90
+ )
91
+ end
92
+
93
+ def http_basic_auth_info
94
+ username, password =
95
+ ActiveSupport::Base64.decode64(http_basic_auth.split.last.to_s).split(/:/, 2)
96
+ end
97
+ end
98
+
99
+ ApiController = APIController ### rails is a bitch - shut her up