pakada 0.2.1 → 0.3.0
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/.yardopts +1 -0
- data/Gemfile +3 -0
- data/README.md +14 -3
- data/lib/pakada/module.rb +14 -6
- data/lib/pakada/version.rb +1 -1
- data/lib/pakada.rb +116 -49
- data/pakada.gemspec +5 -3
- data/spec/module_spec.rb +13 -13
- data/spec/pakada_spec.rb +267 -163
- data/spec/spec_helper.rb +4 -1
- metadata +79 -70
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
- LICENSE ROADMAP.md
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
Modularization contract for web applications
|
2
|
+
============================================
|
3
|
+
|
4
|
+
Pakada is about modular web applications: how should they look like? How should
|
5
|
+
modules interact with each other to fit a certain idea?
|
6
|
+
|
7
|
+
TODO
|
8
|
+
----
|
9
|
+
|
10
|
+
- Thread and Fiber safety
|
11
|
+
- Documentation
|
12
|
+
- Basic CLI for creating projects/modules
|
13
|
+
- Create instances via CLI
|
14
|
+
- Project templates/profiles (e.g. Blog, Forum, etc.)
|
3
15
|
|
4
|
-
TODO: Write documentation
|
data/lib/pakada/module.rb
CHANGED
@@ -9,13 +9,13 @@ class Pakada
|
|
9
9
|
klass.send :include, Hooked
|
10
10
|
|
11
11
|
class << klass
|
12
|
-
attr_reader :
|
12
|
+
attr_reader :pakada_name, :path, :dependencies
|
13
13
|
end
|
14
14
|
|
15
|
-
unless klass.
|
16
|
-
klass.instance_variable_set :@
|
15
|
+
unless klass.pakada_name
|
16
|
+
klass.instance_variable_set :@pakada_name, detect_name(klass.to_s)
|
17
17
|
end
|
18
|
-
unless klass.
|
18
|
+
unless klass.pakada_name
|
19
19
|
raise "Could not detect name for module #{klass}"
|
20
20
|
end
|
21
21
|
|
@@ -25,6 +25,10 @@ class Pakada
|
|
25
25
|
klass.instance_variable_set :@path, detect_path(file)
|
26
26
|
end
|
27
27
|
|
28
|
+
unless klass.dependencies
|
29
|
+
klass.instance_variable_set :@dependencies, []
|
30
|
+
end
|
31
|
+
|
28
32
|
@descendants << klass
|
29
33
|
end
|
30
34
|
|
@@ -56,14 +60,18 @@ class Pakada
|
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
59
|
-
def
|
60
|
-
self.class.
|
63
|
+
def pakada_name
|
64
|
+
self.class.pakada_name
|
61
65
|
end
|
62
66
|
|
63
67
|
def path
|
64
68
|
self.class.path
|
65
69
|
end
|
66
70
|
|
71
|
+
def dependencies
|
72
|
+
self.class.dependencies
|
73
|
+
end
|
74
|
+
|
67
75
|
def boot; end
|
68
76
|
|
69
77
|
def hooks; end
|
data/lib/pakada/version.rb
CHANGED
data/lib/pakada.rb
CHANGED
@@ -1,88 +1,155 @@
|
|
1
|
-
require "rack"
|
2
1
|
require "hooked"
|
2
|
+
require "pathname"
|
3
|
+
require "rack"
|
3
4
|
|
4
5
|
require "pakada/module"
|
5
6
|
require "pakada/version"
|
6
7
|
|
7
8
|
class Pakada
|
8
|
-
|
9
|
-
|
10
|
-
attr_reader :env, :modules, :middleware
|
11
|
-
attr_accessor :app
|
9
|
+
include Hooked
|
12
10
|
|
13
|
-
|
14
|
-
|
11
|
+
@instances = {}
|
12
|
+
@stack = []
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_reader :instances, :stack
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.instance(name = nil, &block)
|
19
|
+
return @stack.last unless name
|
20
|
+
return instances[name] unless block
|
21
|
+
|
22
|
+
unless instances[name]
|
23
|
+
dsl = Struct.new(:urls, :modules, :path).new
|
24
|
+
ret = block.call(dsl)
|
25
|
+
|
26
|
+
config = Hash[*dsl.members.map {|m| m.to_sym }.zip(dsl.values).flatten(1)]
|
27
|
+
instances[name] = new(name, config)
|
28
|
+
else
|
29
|
+
@stack << instances[name]
|
30
|
+
begin
|
31
|
+
ret = block.call(instances[name])
|
32
|
+
ensure
|
33
|
+
@stack.pop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
ret
|
15
38
|
end
|
16
39
|
|
17
|
-
def
|
40
|
+
def self.boot
|
41
|
+
instance(:default) {|ins| ins.urls = ["/"] } if instances.empty?
|
42
|
+
|
43
|
+
@urlmap = Rack::URLMap.new instances.values.inject({}) {|map, ins|
|
44
|
+
ins.urls.each {|url|
|
45
|
+
map[url] = proc {|env|
|
46
|
+
instance(ins.name) { ins.call env }
|
47
|
+
}
|
48
|
+
}
|
49
|
+
map
|
50
|
+
}
|
51
|
+
|
52
|
+
instances.values.each {|ins|
|
53
|
+
instance(ins.name) { ins.boot }
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.call(env)
|
58
|
+
@urlmap.call env
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.env
|
62
|
+
(ENV["RACK_ENV"] || :development).to_sym
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.development?
|
18
66
|
env == :development
|
19
67
|
end
|
20
68
|
|
21
|
-
def testing?
|
69
|
+
def self.testing?
|
22
70
|
env == :testing
|
23
71
|
end
|
24
72
|
|
25
|
-
def
|
73
|
+
def self.staging?
|
74
|
+
env == :staging
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.production?
|
26
78
|
env == :production
|
27
79
|
end
|
28
80
|
|
29
|
-
def
|
30
|
-
modules
|
81
|
+
def self.modules
|
82
|
+
instance.modules if instance
|
31
83
|
end
|
32
84
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
85
|
+
def self.[](pakada_name)
|
86
|
+
modules[pakada_name] if modules
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.middleware
|
90
|
+
instance.middleware if instance
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.urls
|
94
|
+
instance.urls if instance
|
39
95
|
end
|
40
96
|
|
41
|
-
def
|
42
|
-
|
97
|
+
def self.path
|
98
|
+
instance.path if instance
|
43
99
|
end
|
44
100
|
|
45
|
-
|
46
|
-
|
47
|
-
|
101
|
+
attr_reader :name, :urls, :path
|
102
|
+
attr_reader :modules, :middleware
|
103
|
+
|
104
|
+
def initialize(name, config = {})
|
105
|
+
@name = name
|
106
|
+
config[:urls] ||= []
|
107
|
+
config[:modules] ||= Module.descendants
|
108
|
+
config[:path] ||= name == :default ? "" : "instances/#{name}"
|
109
|
+
|
110
|
+
modules, resolved = Array(config[:modules]).dup, false
|
111
|
+
until resolved
|
112
|
+
j ||= modules.size
|
113
|
+
i, j = j, 0
|
114
|
+
|
115
|
+
modules.reverse[0...i].map {|mod|
|
116
|
+
mod.dependencies
|
117
|
+
}.flatten.each {|dep|
|
118
|
+
unless modules.include? dep
|
119
|
+
modules << dep
|
120
|
+
j += 1
|
121
|
+
end
|
122
|
+
}
|
123
|
+
|
124
|
+
resolved = true if j == 0
|
48
125
|
end
|
126
|
+
@modules = modules.inject({}) {|hash, mod|
|
127
|
+
hash[mod.pakada_name] = mod.new; hash
|
128
|
+
}
|
129
|
+
|
130
|
+
path = File.expand_path(config[:path])
|
131
|
+
@urls, @path = Array(config[:urls]), Pathname.new(path)
|
132
|
+
@middleware = []
|
49
133
|
end
|
50
134
|
|
51
|
-
def
|
52
|
-
|
135
|
+
def boot
|
136
|
+
[:hooks, :boot].each {|m|
|
137
|
+
modules.each_value {|mod| mod.send m }
|
138
|
+
} unless Pakada.testing?
|
53
139
|
end
|
54
140
|
|
55
141
|
def call(req_env)
|
56
|
-
to_app.call req_env
|
142
|
+
to_app.call req_env
|
57
143
|
end
|
58
144
|
|
59
145
|
def to_app
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
146
|
+
Rack::Builder.new.tap {|b|
|
147
|
+
middleware.each {|mw| b.use *(Array === mw ? mw : [mw]) }
|
148
|
+
b.run proc {|req_env| request req_env }
|
149
|
+
}.to_app
|
64
150
|
end
|
65
151
|
|
66
152
|
def request(req_env)
|
67
153
|
Rack::Response.new("Hi, I'm Pakada #{VERSION}").finish
|
68
154
|
end
|
69
|
-
|
70
|
-
class << self
|
71
|
-
def instance
|
72
|
-
@instance ||= new
|
73
|
-
end
|
74
|
-
|
75
|
-
def reset_instance
|
76
|
-
@instance = nil
|
77
|
-
end
|
78
|
-
|
79
|
-
def method_missing(m, *args, &block)
|
80
|
-
super(m, *args, &block) unless instance.respond_to? m
|
81
|
-
instance.send m, *args, &block
|
82
|
-
end
|
83
|
-
|
84
|
-
def respond_to?(m, private = false)
|
85
|
-
super(m, private) || instance.respond_to?(m, private)
|
86
|
-
end
|
87
|
-
end
|
88
155
|
end
|
data/pakada.gemspec
CHANGED
@@ -9,17 +9,19 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Lars Gierth"]
|
10
10
|
s.email = ["lars.gierth@gmail.com"]
|
11
11
|
s.homepage = "https://rubygems.org/gems/pakada"
|
12
|
-
s.summary = %q{
|
12
|
+
s.summary = %q{Modularization contract for web applications}
|
13
13
|
#s.description = %q{TODO: Write a gem description}
|
14
14
|
|
15
15
|
s.add_dependency "rack"
|
16
|
-
s.add_dependency "hooked"
|
16
|
+
s.add_dependency "hooked"
|
17
17
|
|
18
18
|
s.add_development_dependency "rspec"
|
19
19
|
s.add_development_dependency "fakefs"
|
20
20
|
s.add_development_dependency "fakefs-require"
|
21
|
+
s.add_development_dependency "yard"
|
22
|
+
s.add_development_dependency "rdiscount"
|
21
23
|
|
22
|
-
s.files = `git ls-files`.split("\n") - [".gitignore", ".
|
24
|
+
s.files = `git ls-files`.split("\n") - [".gitignore", ".travis.yml", "config.ru"]
|
23
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
27
|
s.require_paths = ["lib"]
|
data/spec/module_spec.rb
CHANGED
@@ -67,7 +67,7 @@ describe Pakada::Module do
|
|
67
67
|
klass = Class.new
|
68
68
|
Pakada::Module.should_receive(:detect_name).with(klass.to_s).once { :some_module }
|
69
69
|
klass.send(:include, Pakada::Module)
|
70
|
-
klass.
|
70
|
+
klass.pakada_name.should == :some_module
|
71
71
|
end
|
72
72
|
|
73
73
|
it "crashes if it can't detect a name" do
|
@@ -79,10 +79,10 @@ describe Pakada::Module do
|
|
79
79
|
it "respects an already set name" do
|
80
80
|
Pakada::Module.should_not_receive(:detect_name)
|
81
81
|
klass = Class.new do
|
82
|
-
@
|
82
|
+
@pakada_name = :some_module
|
83
83
|
include Pakada::Module
|
84
84
|
end
|
85
|
-
klass.
|
85
|
+
klass.pakada_name.should == :some_module
|
86
86
|
end
|
87
87
|
|
88
88
|
it "tries to determine the module's path" do
|
@@ -97,7 +97,7 @@ describe Pakada::Module do
|
|
97
97
|
|
98
98
|
Pakada::Module.should_receive(:detect_path).with(file).once { path }
|
99
99
|
klass = Class.new do
|
100
|
-
@
|
100
|
+
@pakada_name = :some_module
|
101
101
|
include Pakada::Module
|
102
102
|
end
|
103
103
|
klass.path.should == path
|
@@ -108,7 +108,7 @@ describe Pakada::Module do
|
|
108
108
|
it "respects an already set path" do
|
109
109
|
Pakada::Module.should_not_receive(:detect_path)
|
110
110
|
klass = Class.new do
|
111
|
-
@
|
111
|
+
@pakada_name = :some_module
|
112
112
|
@path = "/my/path"
|
113
113
|
include Pakada::Module
|
114
114
|
end
|
@@ -117,7 +117,7 @@ describe Pakada::Module do
|
|
117
117
|
|
118
118
|
it "adds the module to the list of descendants" do
|
119
119
|
klass = Class.new do
|
120
|
-
@
|
120
|
+
@pakada_name = :some_module
|
121
121
|
include Pakada::Module
|
122
122
|
end
|
123
123
|
Pakada::Module.descendants.should include(klass)
|
@@ -128,7 +128,7 @@ end
|
|
128
128
|
describe "SomeModule" do
|
129
129
|
before :each do
|
130
130
|
@klass = Class.new do
|
131
|
-
@
|
131
|
+
@pakada_name = :foo
|
132
132
|
@path = "/opt/pakada"
|
133
133
|
include Pakada::Module
|
134
134
|
end
|
@@ -147,13 +147,13 @@ describe "SomeModule" do
|
|
147
147
|
@obj.should respond_to(:hooked)
|
148
148
|
end
|
149
149
|
|
150
|
-
describe ".
|
150
|
+
describe ".pakada_name" do
|
151
151
|
it "contains the module's name" do
|
152
|
-
@klass.
|
152
|
+
@klass.pakada_name.should == :foo
|
153
153
|
end
|
154
154
|
|
155
155
|
it "is read-only" do
|
156
|
-
proc { @klass.
|
156
|
+
proc { @klass.pakada_name = :bar }.should raise_error(NoMethodError)
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
@@ -167,9 +167,9 @@ describe "SomeModule" do
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
170
|
-
describe "#
|
171
|
-
it "is a shortcut for ::
|
172
|
-
@obj.
|
170
|
+
describe "#pakada_name" do
|
171
|
+
it "is a shortcut for ::pakada_name" do
|
172
|
+
@obj.pakada_name.should == @klass.pakada_name
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
data/spec/pakada_spec.rb
CHANGED
@@ -1,235 +1,339 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Pakada do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Pakada.instance.should_receive(:respond_to?).with(:message, true) { true }
|
15
|
-
Pakada.respond_to?(:message, true).should be_true
|
16
|
-
|
17
|
-
Pakada.instance.should_not_receive(:respond_to?).with(:instance)
|
18
|
-
Pakada.respond_to?(:instance)
|
19
|
-
end
|
20
|
-
|
21
|
-
describe ".instance" do
|
22
|
-
it "creates a new Singleton instance and returns it" do
|
23
|
-
Pakada.stub(:new) { double "a Pakada instance" }
|
24
|
-
Pakada.instance.should == Pakada.instance
|
4
|
+
context ".instance" do
|
5
|
+
it "returns the instances stack's top element" do
|
6
|
+
Pakada.instance.should be_nil
|
7
|
+
|
8
|
+
Pakada.instances[:foo] = stub("instance")
|
9
|
+
Pakada.instance(:foo) {|ins|
|
10
|
+
Pakada.instance.should equal(ins)
|
11
|
+
}
|
12
|
+
|
13
|
+
Pakada.instance.should be_nil
|
25
14
|
end
|
26
15
|
end
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Pakada.instance.
|
17
|
+
context ".instance(name)" do
|
18
|
+
let(:ins) { stub "instance" }
|
19
|
+
|
20
|
+
it "returns the specified instance" do
|
21
|
+
Pakada.instance(:i_dont_exist).should be_nil
|
22
|
+
|
23
|
+
Pakada.instances[:foo] = ins
|
24
|
+
Pakada.instance(:foo).should equal(ins)
|
33
25
|
end
|
34
26
|
end
|
35
27
|
|
36
|
-
|
37
|
-
before
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
modules = [:foo, :bar, :baz].inject({}) do |modules, name|
|
43
|
-
modules[name] = stub "#{name} module", :boot => nil
|
44
|
-
modules
|
45
|
-
end
|
46
|
-
subject.stub(:modules).and_return modules
|
28
|
+
context ".instance(name, &block)" do
|
29
|
+
before do
|
30
|
+
Pakada.stub :instances => {
|
31
|
+
:foo => stub("instance: foo"),
|
32
|
+
:bar => stub("instance: bar")
|
33
|
+
}
|
47
34
|
end
|
48
35
|
|
49
|
-
|
50
|
-
|
51
|
-
subject.boot
|
52
|
-
end
|
53
|
-
|
54
|
-
it "calls .load_modules" do
|
55
|
-
subject.should_receive :load_modules
|
56
|
-
subject.boot
|
57
|
-
end
|
36
|
+
let(:foo) { Pakada.instances[:foo] }
|
37
|
+
let(:bar) { Pakada.instances[:bar] }
|
58
38
|
|
59
|
-
it "
|
60
|
-
|
61
|
-
|
39
|
+
it "executes the block in the specified instance's context" do
|
40
|
+
Pakada.instance(:foo) {|ins|
|
41
|
+
ins.should equal(foo)
|
42
|
+
Pakada.instance.should equal(foo)
|
43
|
+
|
44
|
+
Pakada.instance(:bar) {|ins|
|
45
|
+
ins.should equal(bar)
|
46
|
+
Pakada.instance.should equal(bar)
|
47
|
+
}
|
48
|
+
|
49
|
+
Pakada.instance.should equal(foo)
|
50
|
+
}
|
62
51
|
end
|
63
52
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
53
|
+
let(:create) { stub "instance: create_me" }
|
54
|
+
let(:urls) { stub "urls" }
|
55
|
+
let(:modules) { stub "modules" }
|
56
|
+
let(:path) { stub "path" }
|
68
57
|
|
69
|
-
it "
|
70
|
-
|
71
|
-
|
72
|
-
|
58
|
+
it "creates the specified instance if it doesn't exist" do
|
59
|
+
Pakada.should_receive(:new).with(:create_me,
|
60
|
+
:urls => urls, :modules => modules, :path => path
|
61
|
+
).and_return create
|
62
|
+
|
63
|
+
Pakada.instance(:create_me) {|dsl|
|
64
|
+
dsl.urls, dsl.modules, dsl.path = urls, modules, path
|
65
|
+
}
|
66
|
+
|
67
|
+
Pakada.instances[:create_me].should equal(create)
|
73
68
|
end
|
74
69
|
end
|
75
70
|
|
76
|
-
|
77
|
-
before
|
78
|
-
|
71
|
+
context ".boot" do
|
72
|
+
before do
|
73
|
+
Pakada.instance(:foo) {|ins|
|
74
|
+
ins.urls = "/", "/foo"
|
75
|
+
}
|
76
|
+
Pakada.instance(:bar) {}
|
79
77
|
end
|
80
78
|
|
81
|
-
|
82
|
-
|
79
|
+
let(:foo) { Pakada.instance :foo }
|
80
|
+
let(:bar) { Pakada.instance :bar }
|
81
|
+
let(:env) { stub "env" }
|
82
|
+
let(:response) { stub "response" }
|
83
|
+
|
84
|
+
it "creates a Rack::URLMap with end-points for each instance" do
|
85
|
+
foo.should_receive(:call).twice {|e|
|
86
|
+
Pakada.instance.should equal(foo)
|
87
|
+
env.should equal(e)
|
88
|
+
response
|
89
|
+
}
|
90
|
+
|
91
|
+
Rack::URLMap.should_receive(:new) {|map|
|
92
|
+
map.each {|url, app|
|
93
|
+
foo.urls.should include(url)
|
94
|
+
app.call(env).should equal(response)
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
Pakada.boot
|
83
99
|
end
|
84
100
|
|
85
|
-
it "
|
86
|
-
|
87
|
-
|
88
|
-
|
101
|
+
it "calls #boot on each instance" do
|
102
|
+
foo.should_receive :boot
|
103
|
+
bar.should_receive :boot
|
104
|
+
Pakada.boot
|
89
105
|
end
|
90
106
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
107
|
+
let(:default) { Pakada.instance :default }
|
108
|
+
|
109
|
+
it "creates a default instance if there are no others" do
|
110
|
+
Pakada.instances.clear
|
111
|
+
|
112
|
+
Rack::URLMap.should_receive(:new) {|map|
|
113
|
+
default.should_receive(:call) {
|
114
|
+
Pakada.instance.should == default
|
115
|
+
}
|
116
|
+
map["/"].call({})
|
117
|
+
}
|
118
|
+
|
119
|
+
Pakada.boot
|
95
120
|
end
|
96
121
|
end
|
97
122
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
123
|
+
context ".call(env)" do
|
124
|
+
let(:urlmap) { stub "url map" }
|
125
|
+
let(:env) { stub "env" }
|
126
|
+
let(:response) { stub "response" }
|
127
|
+
|
128
|
+
before do
|
129
|
+
Rack::URLMap.stub :new => urlmap
|
130
|
+
Pakada.boot
|
131
|
+
end
|
132
|
+
|
133
|
+
it "forwards to the URL map" do
|
134
|
+
urlmap.should_receive(:call) {|e|
|
135
|
+
e.should equal(env)
|
136
|
+
response
|
137
|
+
}
|
138
|
+
Pakada.call(env).should equal(response)
|
107
139
|
end
|
108
140
|
end
|
109
141
|
|
110
|
-
|
111
|
-
|
112
|
-
subject.stub(:modules).and_return({})
|
113
|
-
[:foo, :bar].each do |m|
|
114
|
-
subject.modules[m] = stub("#{m} module")
|
115
|
-
end
|
116
|
-
end
|
142
|
+
context ".env" do
|
143
|
+
after { ENV.delete "RACK_ENV" }
|
117
144
|
|
118
|
-
it "
|
119
|
-
|
120
|
-
|
145
|
+
it "reflects the runtime environment" do
|
146
|
+
ENV["RACK_ENV"] = "envenvenv"
|
147
|
+
Pakada.env.should equal(:envenvenv)
|
121
148
|
end
|
122
149
|
|
123
|
-
it "
|
124
|
-
|
125
|
-
subject.modules.each_value {|m| m.should_not_receive :hooks }
|
126
|
-
subject.load_hooks
|
150
|
+
it "defaults to :development" do
|
151
|
+
Pakada.env.should equal(:development)
|
127
152
|
end
|
128
153
|
end
|
129
154
|
|
130
|
-
|
131
|
-
it "
|
132
|
-
|
133
|
-
|
155
|
+
context ".development?" do
|
156
|
+
it "is true if env == :development" do
|
157
|
+
Pakada.stub :env => :development
|
158
|
+
Pakada.development?.should be_true
|
134
159
|
end
|
135
160
|
end
|
136
161
|
|
137
|
-
|
138
|
-
it "is
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
subject.stub(:env) { :something }
|
143
|
-
subject.development?.should be_false
|
162
|
+
context ".testing?" do
|
163
|
+
it "is true if env == :testing" do
|
164
|
+
Pakada.stub :env => :testing
|
165
|
+
Pakada.testing?.should be_true
|
144
166
|
end
|
145
167
|
end
|
146
168
|
|
147
|
-
|
148
|
-
it "is
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
subject.stub(:env) { :something }
|
153
|
-
subject.testing?.should be_false
|
169
|
+
context ".staging?" do
|
170
|
+
it "is true if env == :staging" do
|
171
|
+
Pakada.stub :env => :staging
|
172
|
+
Pakada.staging?.should be_true
|
154
173
|
end
|
155
174
|
end
|
156
175
|
|
157
|
-
|
158
|
-
it "is
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
subject.stub(:env) { :something }
|
163
|
-
subject.production?.should be_false
|
176
|
+
context ".production?" do
|
177
|
+
it "is true if env == :production" do
|
178
|
+
Pakada.stub :env => :production
|
179
|
+
Pakada.production?.should be_true
|
164
180
|
end
|
165
181
|
end
|
166
182
|
|
167
|
-
|
168
|
-
|
169
|
-
|
183
|
+
context "#initialize(name, config)" do
|
184
|
+
let(:module1) do
|
185
|
+
stub :new => stub, :pakada_name => :module1, :dependencies => [module2]
|
186
|
+
end
|
187
|
+
let(:module2) do
|
188
|
+
stub :new => stub, :pakada_name => :module2, :dependencies => [module3]
|
189
|
+
end
|
190
|
+
let(:module3) do
|
191
|
+
stub :new => stub, :pakada_name => :module3, :dependencies => []
|
192
|
+
end
|
193
|
+
let(:instance) { Pakada.new :foo, :modules => [module1] }
|
194
|
+
|
195
|
+
it "sets the instance name" do
|
196
|
+
instance.name.should equal(:foo)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "resolves and initializes the modules" do
|
200
|
+
instance.modules[:module1].should equal(module1.new)
|
201
|
+
instance.modules[:module2].should equal(module2.new)
|
202
|
+
instance.modules[:module3].should equal(module3.new)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "sets the URL list" do
|
206
|
+
ins = Pakada.new(:foo, :urls => "http://example.org")
|
207
|
+
ins.urls.should == ["http://example.org"]
|
170
208
|
end
|
171
209
|
|
172
|
-
it "
|
173
|
-
|
210
|
+
it "expands the path" do
|
211
|
+
ins = Pakada.new(:foo, :path => "bar/foo")
|
212
|
+
ins.path.to_s.should == File.join(Dir.pwd, "bar/foo")
|
213
|
+
ins.path.absolute?.should be_true
|
174
214
|
end
|
175
215
|
end
|
176
216
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
217
|
+
context "#initialize(name)" do
|
218
|
+
let(:instance) { Pakada.new :foo }
|
219
|
+
|
220
|
+
before do
|
221
|
+
1.upto(5) {|i|
|
222
|
+
Pakada::Module.descendants << stub({
|
223
|
+
:new => stub("module#{i}"),
|
224
|
+
:pakada_name => :"module#{i}",
|
225
|
+
:dependencies => []
|
226
|
+
})
|
227
|
+
}
|
181
228
|
end
|
182
|
-
|
183
|
-
it "
|
184
|
-
|
185
|
-
Class.new do
|
186
|
-
attr_reader :app, :pos
|
187
|
-
def initialize(app); @app, @pos = app, pos; end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
subject.stub(:middleware).and_return [mw.call(0), mw.call(1)]
|
191
|
-
|
192
|
-
pending "what about middleware insertion order?"
|
229
|
+
|
230
|
+
it "uses an empty URL list" do
|
231
|
+
instance.urls.should be_empty
|
193
232
|
end
|
194
233
|
|
195
|
-
it "
|
196
|
-
|
197
|
-
|
234
|
+
it "uses all available modules" do
|
235
|
+
instance.should have(5).modules
|
236
|
+
end
|
237
|
+
|
238
|
+
it "uses instances/<name> as path" do
|
239
|
+
instance.path.to_s.should == File.join(Dir.pwd, "instances", "foo")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "#initialize(name = :default)" do
|
244
|
+
it "uses the current directory as path" do
|
245
|
+
instance = Pakada.new(:default)
|
246
|
+
instance.path.to_s.should == Dir.pwd
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context "#boot" do
|
251
|
+
let(:foo) { instance.modules[:foo] }
|
252
|
+
let(:bar) { instance.modules[:bar] }
|
253
|
+
let(:instance) { Pakada.instance :instance }
|
254
|
+
|
255
|
+
before do
|
256
|
+
Pakada.instance(:instance) {}
|
257
|
+
instance.stub :modules => {
|
258
|
+
:foo => stub("foo module"),
|
259
|
+
:bar => stub("bar module")
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
263
|
+
it "calls #hooks and #boot on each module" do
|
264
|
+
foo.should_receive :hooks
|
265
|
+
foo.should_receive :boot
|
266
|
+
bar.should_receive :hooks
|
267
|
+
bar.should_receive :boot
|
198
268
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
269
|
+
instance.boot
|
270
|
+
end
|
271
|
+
|
272
|
+
it "does nothing if env == :testing" do
|
273
|
+
Pakada.stub :env => :testing
|
274
|
+
foo.should_not_receive :hooks
|
275
|
+
foo.should_not_receive :boot
|
276
|
+
bar.should_not_receive :hooks
|
277
|
+
bar.should_not_receive :boot
|
204
278
|
|
205
|
-
|
206
|
-
@builder.should_receive(:use).with mw[1]
|
207
|
-
subject.to_app
|
279
|
+
instance.boot
|
208
280
|
end
|
209
281
|
end
|
210
282
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
283
|
+
context "#call(env)" do
|
284
|
+
let(:instance) { Pakada.new :foo }
|
285
|
+
let(:env) { stub "env" }
|
286
|
+
let(:response) { stub "response" }
|
287
|
+
|
288
|
+
before { instance.stub :to_app => stub("#to_app") }
|
289
|
+
|
290
|
+
it "forwards to #to_app.call" do
|
291
|
+
instance.to_app.should_receive(:call) {|e|
|
292
|
+
e.should equal(env)
|
293
|
+
response
|
294
|
+
}
|
215
295
|
|
216
|
-
|
217
|
-
subject.call(req).should == resp
|
296
|
+
instance.call(env).should equal(response)
|
218
297
|
end
|
219
298
|
end
|
220
299
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
300
|
+
context "#to_app" do
|
301
|
+
let(:instance) { Pakada.new :foo }
|
302
|
+
let(:mw1) { stub "middleware#1" }
|
303
|
+
let(:mw2) { [stub("middleware#2"), stub("arg")] }
|
304
|
+
let(:app) { stub "app" }
|
305
|
+
let(:builder) { stub "builder" }
|
306
|
+
let(:env) { stub "env" }
|
307
|
+
let(:response) { stub "response" }
|
308
|
+
|
309
|
+
before { Rack::Builder.stub :new => builder }
|
310
|
+
|
311
|
+
it "builds a Rack app of middleware and endpoint" do
|
312
|
+
builder.should_receive(:use).with mw1
|
313
|
+
builder.should_receive(:use).with *mw2
|
314
|
+
builder.should_receive(:run) {|endpoint|
|
315
|
+
instance.should_receive(:request) {|e|
|
316
|
+
e.should equal(env)
|
317
|
+
response
|
318
|
+
}
|
319
|
+
endpoint.call(env).should equal(response)
|
320
|
+
}
|
321
|
+
builder.should_receive(:to_app) { app }
|
225
322
|
|
226
|
-
|
323
|
+
instance.middleware << mw1 << mw2
|
324
|
+
instance.to_app.should equal(app)
|
227
325
|
end
|
228
326
|
end
|
229
327
|
|
230
|
-
|
231
|
-
|
232
|
-
|
328
|
+
context "#request(env)" do
|
329
|
+
let(:response) { Pakada.instance(:default).request({}) }
|
330
|
+
|
331
|
+
before { Pakada.boot }
|
332
|
+
|
333
|
+
it "returns a tender greeting" do
|
334
|
+
response[0].should equal(200)
|
335
|
+
response[1]["Content-Type"].should == "text/html"
|
336
|
+
response[2].body.join.should match(/Pakada #{Pakada::VERSION}/)
|
233
337
|
end
|
234
338
|
end
|
235
339
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,83 +1,102 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pakada
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Lars Gierth
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-08-01 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: rack
|
17
|
-
requirement: &
|
16
|
+
requirement: &80222130 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
-
- !ruby/object:Gem::Dependency
|
24
|
+
version_requirements: *80222130
|
25
|
+
- !ruby/object:Gem::Dependency
|
27
26
|
name: hooked
|
28
|
-
requirement: &
|
27
|
+
requirement: &80221440 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
|
-
requirements:
|
31
|
-
- -
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version:
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: *80221440
|
36
|
+
- !ruby/object:Gem::Dependency
|
38
37
|
name: rspec
|
39
|
-
requirement: &
|
38
|
+
requirement: &80220860 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
|
-
requirements:
|
42
|
-
- -
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version:
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
45
44
|
type: :development
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
48
|
-
- !ruby/object:Gem::Dependency
|
46
|
+
version_requirements: *80220860
|
47
|
+
- !ruby/object:Gem::Dependency
|
49
48
|
name: fakefs
|
50
|
-
requirement: &
|
49
|
+
requirement: &80220160 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
|
-
requirements:
|
53
|
-
- -
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version:
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
59
|
-
- !ruby/object:Gem::Dependency
|
57
|
+
version_requirements: *80220160
|
58
|
+
- !ruby/object:Gem::Dependency
|
60
59
|
name: fakefs-require
|
61
|
-
requirement: &
|
60
|
+
requirement: &80219690 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version:
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
67
66
|
type: :development
|
68
67
|
prerelease: false
|
69
|
-
version_requirements: *
|
68
|
+
version_requirements: *80219690
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
requirement: &80219040 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *80219040
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rdiscount
|
82
|
+
requirement: &80218590 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *80218590
|
70
91
|
description:
|
71
|
-
email:
|
92
|
+
email:
|
72
93
|
- lars.gierth@gmail.com
|
73
94
|
executables: []
|
74
|
-
|
75
95
|
extensions: []
|
76
|
-
|
77
96
|
extra_rdoc_files: []
|
78
|
-
|
79
|
-
files:
|
97
|
+
files:
|
80
98
|
- .rspec
|
99
|
+
- .yardopts
|
81
100
|
- Gemfile
|
82
101
|
- LICENSE
|
83
102
|
- README.md
|
@@ -91,36 +110,26 @@ files:
|
|
91
110
|
- spec/spec_helper.rb
|
92
111
|
homepage: https://rubygems.org/gems/pakada
|
93
112
|
licenses: []
|
94
|
-
|
95
113
|
post_install_message:
|
96
114
|
rdoc_options: []
|
97
|
-
|
98
|
-
require_paths:
|
115
|
+
require_paths:
|
99
116
|
- lib
|
100
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
118
|
none: false
|
102
|
-
requirements:
|
103
|
-
- -
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
|
106
|
-
|
107
|
-
- 0
|
108
|
-
version: "0"
|
109
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
124
|
none: false
|
111
|
-
requirements:
|
112
|
-
- -
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
|
115
|
-
segments:
|
116
|
-
- 0
|
117
|
-
version: "0"
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
118
129
|
requirements: []
|
119
|
-
|
120
130
|
rubyforge_project:
|
121
|
-
rubygems_version: 1.8.
|
131
|
+
rubygems_version: 1.8.6
|
122
132
|
signing_key:
|
123
133
|
specification_version: 3
|
124
|
-
summary:
|
134
|
+
summary: Modularization contract for web applications
|
125
135
|
test_files: []
|
126
|
-
|