dao 3.3.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,6 +1,6 @@
1
1
  module Dao
2
2
  module InstanceExec
3
- Code = lambda do
3
+ Code = proc do
4
4
  unless Object.new.respond_to?(:instance_exec)
5
5
  module InstanceExecHelper; end
6
6
  include InstanceExecHelper
data/lib/dao/name.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Dao
2
+ class Name < ::String
3
+ def Name.for(name)
4
+ name.is_a?(Name) ? name : Name.new(name)
5
+ end
6
+ end
7
+ end
data/lib/dao/params.rb CHANGED
@@ -2,87 +2,37 @@ module Dao
2
2
  class Params < ::Map
3
3
  # mixins
4
4
  #
5
- include Validations::Mixin
5
+ include Validations
6
6
 
7
7
  # class methods
8
8
  #
9
9
  class << Params
10
- def parse(prefix, params = {}, options = {})
11
- prefix = prefix.to_s
12
- params = Map.new(params || {})
13
- base = Map.new(params || {})
14
- options = Map.options(options || {})
15
- parsed = Params.new
16
- parsed.update(params[prefix]) if params.has_key?(prefix)
17
-
18
- re = %r/^ #{ Regexp.escape(prefix) } (?: [(] ([^)]+) [)] )? $/x
19
-
20
- params.each do |key, value|
21
- next unless(key.is_a?(String) or key.is_a?(Symbol))
22
- key = key.to_s
23
- matched, keys = re.match(key).to_a
24
- next unless matched
25
- next unless keys
26
- keys = keys_for(keys)
27
- parsed.set(keys => value)
28
- base.delete(key)
29
- end
30
-
31
- whitelist = Set.new( [options.getopt([:include, :select, :only])].flatten.compact.map{|k| k.to_s} )
32
- blacklist = Set.new( [options.getopt([:exclude, :reject, :except])].flatten.compact.map{|k| k.to_s} )
33
-
34
- unless blacklist.empty?
35
- base.keys.dup.each do |key|
36
- base.delete(key) if blacklist.include?(key.to_s)
37
- end
38
- end
39
-
40
- unless whitelist.empty?
41
- base.keys.dup.each do |key|
42
- base.delete(key) unless whitelist.include?(key.to_s)
43
- end
44
- end
45
-
46
- if options.getopt(:fold, default=true)
47
- parsed_and_folded = base.merge(parsed)
48
- else
49
- parsed
50
- end
51
- end
52
-
53
- def keys_for(keys)
54
- keys.strip.split(%r/\s*,\s*/).map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
55
- end
56
-
57
- def process(path, params, options = {})
58
- return params if params.is_a?(Params)
59
-
60
- parsed = Params.parse(path, params, options)
61
- return parsed unless parsed.empty?
62
-
63
- return Params.new(params)
64
- end
65
10
  end
66
11
 
67
12
  # instance methods
68
13
  #
69
- attr_accessor :result
70
- attr_accessor :route
71
14
  attr_accessor :path
72
- attr_accessor :status
73
- attr_accessor :errors
74
- attr_accessor :validations
15
+ attr_accessor :route
75
16
  attr_accessor :form
76
17
 
77
18
  def initialize(*args, &block)
78
- @path = Path.default
79
- @status = Status.default
80
- @errors = Errors.new
81
- @validations = Validations.for(self)
82
- @form = Form.for(self)
19
+ options = Dao.options_for!(args)
20
+
21
+ @path = args.shift || options[:path] || Path.default
22
+ @route = options[:route] || Route.default
23
+ @form = options[:form] || Form.for(self)
24
+
25
+ update(options[:params]) if options[:params]
26
+
83
27
  super
84
28
  end
85
29
 
30
+ def attributes
31
+ self
32
+ end
33
+
34
+ fattr(:name){ path }
35
+
86
36
  # look good for inspect
87
37
  #
88
38
  def inspect
data/lib/dao/rack.rb ADDED
@@ -0,0 +1,3 @@
1
+ if defined?(Rack)
2
+ Dao.load %w[ rack/middleware.rb ]
3
+ end
@@ -0,0 +1,5 @@
1
+ module Dao
2
+ module Middleware
3
+ Dao.load %w[ rack/middleware/params_parser.rb ]
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ module Dao
2
+ module Middleware
3
+ class ParamsParser
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @env = env
10
+ #if params = parse_formatted_parameters(env)
11
+ #env["action_dispatch.request.request_parameters"] = params
12
+ #end
13
+
14
+ query_parameters = @env["action_controller.request.query_parameters"]
15
+ request_parameters = @env["action_controller.request.request_parameters"]
16
+
17
+ Rails.logger.info("query_parameters : #{ query_parameters.inspect }")
18
+ Rails.logger.info("request_parameters : #{ request_parameters.inspect }")
19
+
20
+ @app.call(@env)
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/dao/rails.rb CHANGED
@@ -17,26 +17,43 @@ if defined?(Rails)
17
17
 
18
18
  paths.path = ROOT_DIR
19
19
 
20
+ config.autoload_paths += %w( app/models app )
21
+
20
22
  ### config.autoload_paths << APP_DIR
21
23
  ### $LOAD_PATH.push(File.join(Rails.root.to_s, 'app'))
22
24
 
25
+ # drop the dao parameter parser in there...
26
+ #
27
+ #initializer "dao.middleware" do |app|
28
+ #app.middleware.use Dao::Middleware::ParamsParser
29
+ #end
30
+
23
31
  # yes yes, this should probably be somewhere else...
24
32
  #
25
33
  config.after_initialize do
26
34
 
27
35
  ActionController::Base.module_eval do
28
36
 
37
+ before_filter do |controller|
38
+ # set the dao controller
39
+ #
40
+ Dao.current_controller = controller
41
+
42
+ # pre-parse any obvious dao params
43
+ #
44
+ controller.instance_eval do
45
+ Dao.normalize_parameters(params)
46
+ end
47
+ end
48
+
29
49
  # you will likely want to override this!
30
50
  #
31
51
  def current_api
32
52
  @api ||= (
33
53
  api = Api.new
34
54
  %w( real_user effective_user current_user ).each do |attr|
35
- getter = "#{ attr }"
36
- setter = "#{ attr }="
37
- if respond_to?(getter) and api.respond_to?(setter)
38
- api.send(setter, send(getter))
39
- end
55
+ getter, setter = "#{ attr }", "#{ attr }="
56
+ api.send(setter, send(getter)) if(respond_to?(getter) and api.respond_to?(setter))
40
57
  end
41
58
  api
42
59
  )
@@ -1,9 +1,5 @@
1
1
  Description:
2
- rails generate dao api
3
- rails generate dao api controller
4
- rails generate dao paths
2
+ rails generate dao system
5
3
 
6
4
  Example:
7
- rails generate dao api
8
- rails generate dao api controller
9
- rails generate dao paths
5
+ rails generate dao system
@@ -1,15 +1,60 @@
1
1
  class DaoGenerator < Rails::Generators::NamedBase
2
- source_root File.expand_path('../templates', __FILE__)
2
+ source_root(File.expand_path('../templates', __FILE__))
3
3
 
4
- def copy_api_file
5
- copy_file("api.rb", "app/api.rb")
4
+ def copy_files
5
+ ARGV.shift if ARGV.first == name
6
6
 
7
- copy_file("api_controller.rb", "app/controllers/api_controller.rb")
7
+ case name
8
+ when /conducer_controller/
9
+ generate_conducer_controller!
10
+
11
+ when /conducer/
12
+ generate_conducer!
13
+
14
+ when /system/
15
+ generate_system!
16
+
17
+ when /api/
18
+ generate_system!
19
+
20
+ when /conducers/
21
+ generate_system!
22
+
23
+ when /assets/
24
+ generate_system!
8
25
 
26
+ else
27
+ raise "dunno how to generate #{ name.inspect }"
28
+ end
29
+ end
30
+
31
+ 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
+
40
+ def generate_conducer!
41
+ @conducer_name = ARGV.shift.sub(/_?conducer$/i, '') + '_conducer'
42
+ template "conducer.rb", "app/conducers/#{ @conducer_name.underscore }.rb"
43
+ end
44
+
45
+ def generate_system!
46
+ dao_dir = File.join(Rails.root, 'app/dao')
47
+
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")
53
+
54
+ copy_file("api_controller.rb", "app/controllers/api_controller.rb")
9
55
  copy_file("dao_helper.rb", "app/helpers/dao_helper.rb")
10
56
 
11
57
  copy_file("dao.js", "public/javascripts/dao.js")
12
-
13
58
  copy_file("dao.css", "public/stylesheets/dao.css")
14
59
 
15
60
  route("match 'api(/*path)' => 'api#index', :as => 'api'")
@@ -20,11 +65,11 @@ class DaoGenerator < Rails::Generators::NamedBase
20
65
  <<-__
21
66
 
22
67
  config.after_initialize do
23
- require 'app/api.rb'
68
+ require 'app/dao/api.rb'
24
69
  require 'yajl/json_gem'
25
70
  end
26
71
 
27
- config.autoload_paths += %w( app )
72
+ config.autoload_paths += %w( app/models app/dao app/dao/apis app/dao/conducers )
28
73
 
29
74
  ### config.action_view.javascript_expansions[:defaults] ||= []
30
75
  ### config.action_view.javascript_expansions[:defaults] += %( dao )
@@ -12,12 +12,12 @@ Api =
12
12
 
13
13
  ##
14
14
  #
15
- doc '/ping - hello world without a user'
15
+ desc '/ping - hello world without a user'
16
16
  call('/ping'){
17
17
  data.update :time => Time.now
18
18
  }
19
19
 
20
- doc '/pong - hello world with a user'
20
+ desc '/pong - hello world with a user'
21
21
  call('/pong'){
22
22
  require_current_user!
23
23
  data.update :time => Time.now
@@ -48,6 +48,8 @@ Api =
48
48
  alias_method('user=', 'effective_user=')
49
49
  alias_method('current_user', 'effective_user')
50
50
  alias_method('current_user=', 'effective_user=')
51
+ alias_method('effective_user?', 'effective_user')
52
+ alias_method('real_user?', 'real_user')
51
53
 
52
54
  def api
53
55
  self
@@ -77,7 +79,7 @@ Api =
77
79
  end
78
80
 
79
81
  def require_real_user!
80
- unless effective_user?
82
+ unless real_user?
81
83
  status :unauthorized
82
84
  return!
83
85
  end
@@ -89,9 +91,23 @@ Api =
89
91
  alias_method('require_user!', 'require_current_user!')
90
92
  end
91
93
 
94
+ ## look for any other apis to load
95
+ #
96
+ %w( api apis ).each do |dir|
97
+ glob = File.expand_path(File.join(Rails.root, "app/#{ dir }/**/*.rb"))
98
+ files = Dir.glob(glob).sort
99
+ files.each{|file| ::Kernel.load(file)}
100
+ end
92
101
 
93
- unloadable(Api)
102
+ ## mo betta in development
103
+ #
104
+ unloadable(Api)
94
105
 
95
- def api(*args, &block)
96
- Api.new(*args, &block)
97
- end
106
+ ## top level method shortcut
107
+ #
108
+ module Kernel
109
+ protected
110
+ def api(*args, &block)
111
+ Api.new(*args, &block)
112
+ end
113
+ end
@@ -3,8 +3,9 @@ class APIController < ApplicationController
3
3
 
4
4
  skip_before_filter :verify_authenticity_token
5
5
 
6
- before_filter :setup_path
7
6
  before_filter :setup_api
7
+ before_filter :setup_mode
8
+ before_filter :setup_path
8
9
 
9
10
  WhiteList = Set.new( %w( ping index ) )
10
11
  BlackList = Set.new( %w( ) )
@@ -17,8 +18,7 @@ class APIController < ApplicationController
17
18
  protected
18
19
 
19
20
  def call(path, params)
20
- mode = params['mode'] || (request.get? ? 'read' : 'write')
21
- result = api.mode(mode).call(path, params)
21
+ @result = api.mode(@mode).call(path, params)
22
22
  end
23
23
 
24
24
  def respond_with(object, options = {})
@@ -30,25 +30,42 @@ protected
30
30
  respond_to do |wants|
31
31
  wants.json{ render :json => json, :status => status }
32
32
  wants.html{ render :text => json, :status => status, :content_type => 'text/plain' }
33
+ wants.xml{ render :text => 'no soup for you!', :status => 403 }
33
34
  end
34
35
  end
35
36
 
36
37
  def json_for(object)
37
- if Rails.env.production?
38
- ::JSON.generate(object)
39
- else
40
- ::JSON.pretty_generate(object, :max_nesting => 0)
38
+ begin
39
+ if Rails.env.production?
40
+ ::JSON.generate(object)
41
+ else
42
+ ::JSON.pretty_generate(object, :max_nesting => 0)
43
+ end
44
+ rescue Object => e
45
+ Rails.logger.error(e)
46
+ YAML.load( object.to_yaml ).to_json
41
47
  end
42
48
  end
43
49
 
44
50
  def setup_path
45
51
  @path = params[:path] || params[:action] || 'index'
52
+ unless api.route?(@path) or @path=='index'
53
+ render :nothing => true, :status => 404
54
+ end
55
+ end
56
+
57
+ def setup_mode
58
+ @mode = params['mode'] || (request.get? ? 'read' : 'write')
46
59
  end
47
60
 
48
61
  def path
49
62
  @path
50
63
  end
51
64
 
65
+ def mode
66
+ @mode
67
+ end
68
+
52
69
  ##
53
70
  # you'll likely want to customize this for you app as it makes a few
54
71
  # assumptions about how to find and authenticate users
@@ -0,0 +1,64 @@
1
+ <%
2
+
3
+ class_name = @conducer_name.camelize
4
+ model_name = class_name.sub(/Conducer/, '')
5
+
6
+ -%>
7
+ 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
18
+
19
+ def find(id)
20
+ raise NotImplementedError, <<-__
21
+ this needs to return an instance based on the id
22
+ __
23
+ end
24
+ end
25
+
26
+ ## instance_methods
27
+ #
28
+ def initialize
29
+ run_callbacks :initialize do
30
+ end
31
+ end
32
+
33
+ def save
34
+ run_callbacks :save do
35
+ return(false) unless valid?
36
+
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
+ __
43
+
44
+ true
45
+ end
46
+ end
47
+
48
+ 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
62
+ end
63
+ end
64
+ end