dao 3.1.0 → 3.1.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.
- 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
|