dao 3.1.0 → 3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -0
- data/a.rb +75 -20
- data/dao.gemspec +2 -1
- data/lib/dao.rb +1 -8
- data/lib/dao/api/context.rb +10 -5
- data/lib/dao/api/interfaces.rb +20 -12
- data/lib/dao/interface.rb +13 -1
- data/lib/dao/rails.rb +9 -4
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +5 -2
- data/test/leak.rb +86 -0
- metadata +5 -4
data/README
CHANGED
@@ -106,6 +106,7 @@ READING
|
|
106
106
|
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
|
107
107
|
http://www.paperplanes.de/2010/5/7/activerecord_callbacks_ruined_my_life.html
|
108
108
|
http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.xml
|
109
|
+
http://pragdave.blogs.pragprog.com/pragdave/2007/03/the_radar_archi.html
|
109
110
|
|
110
111
|
INSTALL
|
111
112
|
gem 'dao', :path => File.expand_path('..') ### Gemfile
|
data/a.rb
CHANGED
@@ -1,25 +1,80 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
##
|
2
|
+
#
|
3
|
+
require 'dao'
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'activesupport', '>= 3.0.7'
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/dependencies'
|
8
|
+
|
9
|
+
##
|
10
|
+
#
|
11
|
+
leak =
|
12
|
+
lambda do
|
13
|
+
Api =
|
14
|
+
Dao.api do
|
15
|
+
1000.times do |i|
|
16
|
+
call("/foobar-#{ i }") do
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
api = Api.new
|
22
|
+
|
23
|
+
result = api.call('/foobar-1')
|
24
|
+
p result
|
25
|
+
|
26
|
+
ActiveSupport::Dependencies.unloadable(Api)
|
27
|
+
ActiveSupport::Dependencies.remove_unloadable_constants!
|
7
28
|
end
|
8
|
-
end
|
9
29
|
|
10
|
-
|
30
|
+
##
|
31
|
+
#
|
32
|
+
n = 10
|
33
|
+
|
34
|
+
leak.call()
|
35
|
+
|
36
|
+
GC.start
|
37
|
+
leak.call()
|
38
|
+
GC.start
|
39
|
+
|
40
|
+
p :before => Process.size
|
41
|
+
|
42
|
+
|
43
|
+
GC.start
|
44
|
+
leak.call()
|
45
|
+
GC.start
|
46
|
+
|
47
|
+
p :after => Process.size
|
48
|
+
|
49
|
+
|
50
|
+
|
11
51
|
|
12
|
-
result = api.call('/users/1/comments/2')
|
13
|
-
puts result.form.input(:user_id)
|
14
|
-
puts result.form.input(:comment_id)
|
15
|
-
puts
|
16
52
|
|
17
|
-
result = api.call('/users/comments', :user_id => 1, :comment_id => 2)
|
18
|
-
puts result.form.input(:user_id)
|
19
|
-
puts result.form.input(:comment_id)
|
20
|
-
puts
|
21
53
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
##
|
62
|
+
#
|
63
|
+
BEGIN {
|
64
|
+
|
65
|
+
module Process
|
66
|
+
def self.size pid = Process.pid
|
67
|
+
stdout = `ps wwwux -p #{ pid }`.split(%r/\n/)
|
68
|
+
vsize, rsize = stdout.last.split(%r/\s+/)[4,2]
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.vsize
|
72
|
+
size.first
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.rsize
|
76
|
+
size.last
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
}
|
data/dao.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "dao"
|
6
|
-
spec.version = "3.1.
|
6
|
+
spec.version = "3.1.1"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "dao"
|
9
9
|
spec.description = "description: dao kicks the ass"
|
@@ -69,6 +69,7 @@ Gem::Specification::new do |spec|
|
|
69
69
|
"test",
|
70
70
|
"test/dao_test.rb",
|
71
71
|
"test/helper.rb",
|
72
|
+
"test/leak.rb",
|
72
73
|
"test/testing.rb",
|
73
74
|
"test/units"]
|
74
75
|
|
data/lib/dao.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# dao libs
|
11
11
|
#
|
12
12
|
module Dao
|
13
|
-
Version = '3.1.
|
13
|
+
Version = '3.1.1' unless defined?(Version)
|
14
14
|
|
15
15
|
def version
|
16
16
|
Dao::Version
|
@@ -96,10 +96,3 @@
|
|
96
96
|
unless defined?(D)
|
97
97
|
D = Dao
|
98
98
|
end
|
99
|
-
|
100
|
-
if defined?(Rails.env)
|
101
|
-
unless Rails.env.production?
|
102
|
-
unloadable(Dao)
|
103
|
-
unloadable(D)
|
104
|
-
end
|
105
|
-
end
|
data/lib/dao/api/context.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dao
|
2
2
|
class Context
|
3
|
-
Attrs = %w( api route path interface
|
3
|
+
Attrs = %w( api route path interface args status errors params result data form validations )
|
4
4
|
|
5
5
|
Attrs.each{|a| attr_accessor(a)}
|
6
6
|
|
@@ -19,8 +19,12 @@ module Dao
|
|
19
19
|
params = result.params
|
20
20
|
params.update(parsed_params)
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
args =
|
23
|
+
if interface.arity < 1
|
24
|
+
[params, result]
|
25
|
+
else
|
26
|
+
[params, result].slice(0, interface.arity)
|
27
|
+
end
|
24
28
|
|
25
29
|
# build the context
|
26
30
|
#
|
@@ -29,7 +33,6 @@ module Dao
|
|
29
33
|
context.interface = interface
|
30
34
|
context.route = route
|
31
35
|
context.path = path
|
32
|
-
context.method = method
|
33
36
|
context.args = args
|
34
37
|
context.status = Status.default
|
35
38
|
context.errors = Errors.new
|
@@ -56,8 +59,10 @@ module Dao
|
|
56
59
|
context
|
57
60
|
end
|
58
61
|
|
62
|
+
include InstanceExec
|
63
|
+
|
59
64
|
def call
|
60
|
-
|
65
|
+
api.instance_exec(*args, &interface)
|
61
66
|
end
|
62
67
|
end
|
63
68
|
end
|
data/lib/dao/api/interfaces.rb
CHANGED
@@ -3,8 +3,16 @@ module Dao
|
|
3
3
|
# class methods
|
4
4
|
#
|
5
5
|
class << Api
|
6
|
-
def
|
7
|
-
|
6
|
+
def unload!
|
7
|
+
state.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
def state
|
11
|
+
@state ||= {
|
12
|
+
:interfaces => {},
|
13
|
+
:blocks => {},
|
14
|
+
:docs => []
|
15
|
+
}
|
8
16
|
end
|
9
17
|
|
10
18
|
def interface(path, &block)
|
@@ -13,24 +21,22 @@ module Dao
|
|
13
21
|
|
14
22
|
route = routes.add(path) if Route.like?(path)
|
15
23
|
|
16
|
-
|
17
|
-
module_eval{
|
18
|
-
define_method(path + '/interface', &block)
|
19
|
-
instance_method(path + '/interface')
|
20
|
-
}
|
21
|
-
|
22
|
-
interface = Interface.new(
|
24
|
+
interface = Interface.new({
|
23
25
|
'api' => api,
|
24
26
|
'path' => path,
|
25
27
|
'route' => route,
|
26
|
-
'
|
28
|
+
'block' => block,
|
27
29
|
'doc' => docs.pop
|
28
|
-
)
|
30
|
+
})
|
29
31
|
|
30
32
|
interfaces[path] = interface
|
31
33
|
end
|
32
34
|
alias_method('call', 'interface')
|
33
35
|
|
36
|
+
def interfaces
|
37
|
+
state[:interfaces]
|
38
|
+
end
|
39
|
+
|
34
40
|
def description(string)
|
35
41
|
doc(:description => Dao.unindent(string))
|
36
42
|
end
|
@@ -48,7 +54,7 @@ module Dao
|
|
48
54
|
end
|
49
55
|
|
50
56
|
def docs
|
51
|
-
|
57
|
+
state[:docs]
|
52
58
|
end
|
53
59
|
|
54
60
|
def index
|
@@ -89,6 +95,8 @@ module Dao
|
|
89
95
|
if Route.like?(path)
|
90
96
|
route = Route.new(path)
|
91
97
|
path = route.path_for(params)
|
98
|
+
else
|
99
|
+
route = path
|
92
100
|
end
|
93
101
|
end
|
94
102
|
|
data/lib/dao/interface.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dao
|
2
2
|
class Interface
|
3
|
-
Attrs = %w( api path route
|
3
|
+
Attrs = %w( api path route block doc )
|
4
4
|
Attrs.each{|attr| attr_accessor(attr)}
|
5
5
|
|
6
6
|
def initialize(options = {})
|
@@ -12,5 +12,17 @@ module Dao
|
|
12
12
|
send("#{ key }=", val)
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
def arity
|
17
|
+
block.arity
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(*args)
|
21
|
+
block.call(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_proc
|
25
|
+
block
|
26
|
+
end
|
15
27
|
end
|
16
28
|
end
|
data/lib/dao/rails.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
if defined?(Rails)
|
2
|
+
|
2
3
|
module Dao
|
4
|
+
## support unloadable
|
5
|
+
#
|
6
|
+
def Api.before_remove_const
|
7
|
+
unload!
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
#
|
3
12
|
class Engine < Rails::Engine
|
4
13
|
GEM_DIR = File.expand_path(__FILE__ + '/../../../')
|
5
14
|
ROOT_DIR = File.join(GEM_DIR, 'lib/dao/rails')
|
@@ -10,10 +19,6 @@ if defined?(Rails)
|
|
10
19
|
|
11
20
|
### config.autoload_paths << APP_DIR
|
12
21
|
### $LOAD_PATH.push(File.join(Rails.root.to_s, 'app'))
|
13
|
-
#config.after_initialize do
|
14
|
-
#unloadable(Dao)
|
15
|
-
#end
|
16
|
-
|
17
22
|
|
18
23
|
# yes yes, this should probably be somewhere else...
|
19
24
|
#
|
@@ -24,9 +24,8 @@ protected
|
|
24
24
|
def respond_with(object, options = {})
|
25
25
|
json = json_for(object)
|
26
26
|
|
27
|
-
status = object.status
|
27
|
+
status = object.status rescue (options[:status] || 200)
|
28
28
|
status = status.code if status.respond_to?(:code)
|
29
|
-
status = options[:status] || 200 unless status
|
30
29
|
|
31
30
|
respond_to do |wants|
|
32
31
|
wants.json{ render :json => json, :status => status }
|
@@ -50,6 +49,10 @@ protected
|
|
50
49
|
@path
|
51
50
|
end
|
52
51
|
|
52
|
+
##
|
53
|
+
# you'll likely want to customize this for you app as it makes a few
|
54
|
+
# assumptions about how to find and authenticate users
|
55
|
+
#
|
53
56
|
def setup_api
|
54
57
|
if white_listed?(path)
|
55
58
|
@api = Api.new
|
data/test/leak.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
##
|
2
|
+
#
|
3
|
+
require 'rubygems'
|
4
|
+
#gem 'activesupport', '>= 3.0.7'
|
5
|
+
#require 'active_support'
|
6
|
+
#require 'active_support/dependencies'
|
7
|
+
|
8
|
+
require 'rails/all'
|
9
|
+
require 'dao'
|
10
|
+
|
11
|
+
##
|
12
|
+
#
|
13
|
+
gc =
|
14
|
+
lambda do
|
15
|
+
10.times{ GC.start }
|
16
|
+
end
|
17
|
+
|
18
|
+
leak =
|
19
|
+
lambda do
|
20
|
+
Api =
|
21
|
+
Dao.api do
|
22
|
+
1000.times do |i|
|
23
|
+
call("/foobar-#{ i }") do
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
api = Api.new
|
29
|
+
|
30
|
+
result = api.call('/foobar-1')
|
31
|
+
result.route || abort(result.inspect)
|
32
|
+
|
33
|
+
ActiveSupport::Dependencies.unloadable(Api)
|
34
|
+
ActiveSupport::Dependencies.remove_unloadable_constants!
|
35
|
+
gc.call()
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
#
|
40
|
+
n = 10
|
41
|
+
|
42
|
+
paths = 0
|
43
|
+
ObjectSpace.each_object(Dao::Path){ paths += 1}
|
44
|
+
p 'paths' => paths
|
45
|
+
|
46
|
+
leak.call()
|
47
|
+
before = Process.size
|
48
|
+
|
49
|
+
paths = 0
|
50
|
+
ObjectSpace.each_object(Dao::Path){ paths += 1}
|
51
|
+
p 'paths' => paths
|
52
|
+
|
53
|
+
leak.call()
|
54
|
+
after = Process.size
|
55
|
+
|
56
|
+
paths = 0
|
57
|
+
ObjectSpace.each_object(Dao::Path){ paths += 1}
|
58
|
+
p 'paths' => paths
|
59
|
+
|
60
|
+
delta = [after.first - before.first, after.last - before.last]
|
61
|
+
|
62
|
+
p :before => before
|
63
|
+
p :after => after
|
64
|
+
p :delta => delta
|
65
|
+
|
66
|
+
|
67
|
+
##
|
68
|
+
#
|
69
|
+
BEGIN {
|
70
|
+
|
71
|
+
module Process
|
72
|
+
def self.size pid = Process.pid
|
73
|
+
stdout = `ps wwwux -p #{ pid }`.split(%r/\n/)
|
74
|
+
vsize, rsize = stdout.last.split(%r/\s+/)[4,2].map{|i| i.to_i}
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.vsize
|
78
|
+
size.first.to_i
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.rsize
|
82
|
+
size.last.to_i
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dao
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 3.1.
|
9
|
+
- 1
|
10
|
+
version: 3.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ara T. Howard
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-06-07 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- lib/dao/validations/common.rb
|
79
79
|
- test/dao_test.rb
|
80
80
|
- test/helper.rb
|
81
|
+
- test/leak.rb
|
81
82
|
- test/testing.rb
|
82
83
|
has_rdoc: true
|
83
84
|
homepage: https://github.com/ahoward/dao
|