zorglub 0.0.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/Changelog +2 -0
- data/MIT-LICENSE +18 -0
- data/README.rdoc +55 -0
- data/Rakefile +58 -0
- data/lib/zorglub/app.rb +45 -0
- data/lib/zorglub/config.rb +66 -0
- data/lib/zorglub/node.rb +196 -0
- data/lib/zorglub/session.rb +81 -0
- data/lib/zorglub.rb +14 -0
- data/spec/app_spec.rb +43 -0
- data/spec/data/layout/default +0 -0
- data/spec/data/layout/main.spec +0 -0
- data/spec/data/view/node0/do_partial +0 -0
- data/spec/data/view/node0/do_render +0 -0
- data/spec/node_spec.rb +157 -0
- data/spec/spec_helper.rb +136 -0
- data/tasks/ann.rake +83 -0
- data/tasks/constants.rb +118 -0
- data/tasks/gem.rake +196 -0
- data/tasks/git.rake +38 -0
- data/tasks/helpers.rb +130 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +35 -0
- data/tasks/rdoc.rake +46 -0
- data/tasks/rubyforge.rake +54 -0
- data/tasks/setup.rb +129 -0
- data/tasks/spec.rake +44 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +41 -0
- metadata +122 -0
data/Changelog
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2011-2012 Jérémy Zurcher
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
zorglub
|
2
|
+
by Jérémy Zurcher
|
3
|
+
http://cgit.asynk.ch/cgi-bin/cgit/zorglub
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
a nano web application framework based on rack[http://rack.rubyforge.org/]
|
8
|
+
|
9
|
+
== FEATURES:
|
10
|
+
|
11
|
+
* class#method mapping scheme (/class_mapping/method_name/*args)
|
12
|
+
* class level layout and engine specification
|
13
|
+
* method level layout, engine and view specification
|
14
|
+
* before_all and after_all methods callbacks
|
15
|
+
* redirection
|
16
|
+
* partial
|
17
|
+
* class level inherited variables
|
18
|
+
* session
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
For a simple test application run:
|
23
|
+
* rackup ./example/sample.ru
|
24
|
+
|
25
|
+
Don't forget to look at
|
26
|
+
* the spec/ folder
|
27
|
+
|
28
|
+
== REQUIREMENTS:
|
29
|
+
|
30
|
+
* rack
|
31
|
+
|
32
|
+
== DOWNLOAD/INSTALL:
|
33
|
+
|
34
|
+
From rubygems:
|
35
|
+
|
36
|
+
[sudo] gem install zorglub
|
37
|
+
|
38
|
+
or from the git repository on github:
|
39
|
+
|
40
|
+
git clone git://github.com/jeremyz/zorglub.git
|
41
|
+
cd zorglub
|
42
|
+
rake gem:install
|
43
|
+
|
44
|
+
== RESOURCES:
|
45
|
+
|
46
|
+
You can find this project in a few places:
|
47
|
+
|
48
|
+
Online repositories:
|
49
|
+
|
50
|
+
* https://github.com/jeremyz/zorglub
|
51
|
+
* http://cgit.asynk.ch/cgi-bin/cgit/zorglub/
|
52
|
+
|
53
|
+
== LICENSE:
|
54
|
+
|
55
|
+
See MIT-LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
require './lib/zorglub.rb'
|
4
|
+
load './tasks/setup.rb'
|
5
|
+
#
|
6
|
+
# Project general information
|
7
|
+
PROJ.name = 'zorglub'
|
8
|
+
PROJ.authors = 'Jérémy Zurcher'
|
9
|
+
PROJ.email = 'jeremy@asynk.ch'
|
10
|
+
PROJ.url = 'http://cgit.asynk.ch/cgi-bin/cgit/zorglub'
|
11
|
+
PROJ.version = Zorglub::VERSION
|
12
|
+
PROJ.rubyforge.name = 'FIXME'
|
13
|
+
PROJ.readme_file = 'README.rdoc'
|
14
|
+
#
|
15
|
+
# Annoucement
|
16
|
+
PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
|
17
|
+
PROJ.ann.email[:from] = 'jeremy@asynk.ch'
|
18
|
+
PROJ.ann.email[:to] = ['FIXME']
|
19
|
+
PROJ.ann.email[:server] = 'FIXME'
|
20
|
+
PROJ.ann.email[:tls] = false
|
21
|
+
# Gem specifications
|
22
|
+
PROJ.gem.need_tar = false
|
23
|
+
PROJ.gem.files = %w(Changelog MIT-LICENSE README.rdoc Rakefile) + Dir.glob("{ext,lib,spec,tasks}/**/*[^~]").reject { |fn| test ?d, fn }
|
24
|
+
PROJ.gem.platform = Gem::Platform::RUBY
|
25
|
+
PROJ.gem.required_ruby_version = ">= 1.9.2"
|
26
|
+
#
|
27
|
+
# Override Mr. Bones autogenerated extensions and force ours in
|
28
|
+
#PROJ.gem.extras['extensions'] = %w(ext/extconf.rb)
|
29
|
+
#PROJ.gem.extras['required_ruby_version'] = ">= 1.9.2"
|
30
|
+
#
|
31
|
+
# RDoc
|
32
|
+
PROJ.rdoc.exclude << '^ext\/'
|
33
|
+
PROJ.rdoc.opts << '-x' << 'ext'
|
34
|
+
#
|
35
|
+
# Ruby
|
36
|
+
PROJ.ruby_opts = []
|
37
|
+
PROJ.ruby_opts << '-I' << 'lib'
|
38
|
+
#
|
39
|
+
# RSpec
|
40
|
+
PROJ.spec.files.exclude /rbx/
|
41
|
+
PROJ.spec.opts << '--color'
|
42
|
+
#
|
43
|
+
# Rcov
|
44
|
+
PROJ.rcov.opts << '-I lib'
|
45
|
+
#
|
46
|
+
# Dependencies
|
47
|
+
depend_on 'rack'
|
48
|
+
depend_on 'rake', '>=0.8.0'
|
49
|
+
#
|
50
|
+
task :default => [:spec]
|
51
|
+
#
|
52
|
+
desc "Build all packages"
|
53
|
+
task :package => 'gem:package'
|
54
|
+
#
|
55
|
+
desc "Install the gem locally"
|
56
|
+
task :install => 'gem:install'
|
57
|
+
#
|
58
|
+
# EOF
|
data/lib/zorglub/app.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
require 'rack'
|
4
|
+
#
|
5
|
+
module Zorglub
|
6
|
+
#
|
7
|
+
class App < Rack::URLMap
|
8
|
+
#
|
9
|
+
def initialize map={}, &block
|
10
|
+
super
|
11
|
+
@map = map
|
12
|
+
instance_eval &block if block_given?
|
13
|
+
remap @map
|
14
|
+
end
|
15
|
+
#
|
16
|
+
def map location, object
|
17
|
+
return unless location and object
|
18
|
+
raise Exception.new "#{@map[location]} already mapped to #{location}" if @map.has_key? location
|
19
|
+
object.app = self
|
20
|
+
@map.merge! location.to_s=>object
|
21
|
+
remap @map
|
22
|
+
end
|
23
|
+
#
|
24
|
+
def delete location
|
25
|
+
@map.delete location
|
26
|
+
remap @map
|
27
|
+
end
|
28
|
+
#
|
29
|
+
def at location
|
30
|
+
@map[location]
|
31
|
+
end
|
32
|
+
#
|
33
|
+
def to object
|
34
|
+
@map.invert[object]
|
35
|
+
end
|
36
|
+
#
|
37
|
+
def to_hash
|
38
|
+
@map.dup
|
39
|
+
end
|
40
|
+
#
|
41
|
+
end
|
42
|
+
#
|
43
|
+
end
|
44
|
+
#
|
45
|
+
# EOF
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
module Zorglub
|
4
|
+
#
|
5
|
+
class Config
|
6
|
+
@options = {
|
7
|
+
:root => '.',
|
8
|
+
:engine => nil,
|
9
|
+
:layout => 'default',
|
10
|
+
:view_dir => 'view',
|
11
|
+
:layout_dir => 'layout',
|
12
|
+
:session_on => false
|
13
|
+
}
|
14
|
+
@engines = { }
|
15
|
+
class << self
|
16
|
+
#
|
17
|
+
def [] k
|
18
|
+
@options[k]
|
19
|
+
end
|
20
|
+
#
|
21
|
+
def []= k, v
|
22
|
+
@options[k]=v
|
23
|
+
end
|
24
|
+
#
|
25
|
+
def view_base_path
|
26
|
+
p = @options[:view_path]
|
27
|
+
( p.nil? ? File.join(@options[:root], @options[:view_dir]) : p )
|
28
|
+
end
|
29
|
+
#
|
30
|
+
def layout_base_path
|
31
|
+
p = @options[:layout_path]
|
32
|
+
( p.nil? ? File.join(@options[:root], @options[:layout_dir]) : p )
|
33
|
+
end
|
34
|
+
#
|
35
|
+
def register_engine name, ext, proc
|
36
|
+
return unless name
|
37
|
+
@engines[name]=[ ext, proc ]
|
38
|
+
end
|
39
|
+
#
|
40
|
+
def engine_ext engine
|
41
|
+
e = @engines[engine]
|
42
|
+
return '' if e.nil?
|
43
|
+
x=e[0]
|
44
|
+
( x.nil? ? '' : '.'+x )
|
45
|
+
end
|
46
|
+
#
|
47
|
+
def engine_proc engine
|
48
|
+
e = @engines[engine]
|
49
|
+
( e.nil? ? nil : e[1] )
|
50
|
+
end
|
51
|
+
#
|
52
|
+
end
|
53
|
+
#
|
54
|
+
def self.method_missing m, *args, &block
|
55
|
+
if m=~/(.*)=$/
|
56
|
+
@options[$1.to_sym]=args[0]
|
57
|
+
else
|
58
|
+
@options[m.to_sym]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
#
|
62
|
+
end
|
63
|
+
#
|
64
|
+
end
|
65
|
+
#
|
66
|
+
# EOF
|
data/lib/zorglub/node.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
module Zorglub
|
4
|
+
#
|
5
|
+
class Node
|
6
|
+
#
|
7
|
+
@hooks = {
|
8
|
+
:before_all => [],
|
9
|
+
:after_all => [],
|
10
|
+
}
|
11
|
+
#
|
12
|
+
@inherited_vars = { }
|
13
|
+
#
|
14
|
+
class << self
|
15
|
+
#
|
16
|
+
attr_reader :hooks, :inherited_vars
|
17
|
+
#
|
18
|
+
def inherited sub
|
19
|
+
sub.layout layout
|
20
|
+
sub.engine engine
|
21
|
+
sub.instance_variable_set :@inherited_vars, {}
|
22
|
+
@inherited_vars.each do |s,v| sub.inherited_var s, *v end
|
23
|
+
end
|
24
|
+
#
|
25
|
+
def engine engine=nil
|
26
|
+
@engine = engine unless engine.nil? or engine.empty?
|
27
|
+
@engine ||= Config.engine
|
28
|
+
end
|
29
|
+
#
|
30
|
+
def layout layout=nil
|
31
|
+
@layout = layout unless layout.nil? or layout.empty?
|
32
|
+
@layout ||= Config.layout
|
33
|
+
end
|
34
|
+
#
|
35
|
+
def inherited_var sym, *args
|
36
|
+
var = @inherited_vars[sym] ||=[]
|
37
|
+
unless args.empty?
|
38
|
+
var.concat args
|
39
|
+
var.uniq!
|
40
|
+
end
|
41
|
+
var
|
42
|
+
end
|
43
|
+
#
|
44
|
+
attr_writer :app
|
45
|
+
def map app, location
|
46
|
+
@app = app
|
47
|
+
@app.map location, self
|
48
|
+
end
|
49
|
+
#
|
50
|
+
def r *args
|
51
|
+
@r ||= @app.to self
|
52
|
+
(args.empty? ? @r : File.join( @r, args.map { |x| x.to_s } ) )
|
53
|
+
end
|
54
|
+
#
|
55
|
+
def call env
|
56
|
+
meth, *args = env['PATH_INFO'].sub(/^\//,'').split '/'
|
57
|
+
meth||= 'index'
|
58
|
+
node = self.new env, {:engine=>engine,:layout=>layout,:view=>r(meth),:method=>meth,:args=>args}
|
59
|
+
return error_404 node if not node.respond_to? meth
|
60
|
+
node.realize!
|
61
|
+
end
|
62
|
+
#
|
63
|
+
def partial meth, *args
|
64
|
+
node = self.new nil, {:engine=>engine,:layout=>nil,:view=>r(meth),:method=>meth.to_s,:args=>args}
|
65
|
+
return error_404 node if not node.respond_to? meth
|
66
|
+
node.feed!
|
67
|
+
node.content
|
68
|
+
end
|
69
|
+
#
|
70
|
+
def call_before_hooks obj
|
71
|
+
Node.hooks[:before_all].each do |blk| blk.call obj end
|
72
|
+
end
|
73
|
+
#
|
74
|
+
def before_all &blk
|
75
|
+
Node.hooks[:before_all]<< blk
|
76
|
+
Node.hooks[:before_all].uniq!
|
77
|
+
end
|
78
|
+
#
|
79
|
+
def call_after_hooks obj
|
80
|
+
Node.hooks[:after_all].each do |blk| blk.call obj end
|
81
|
+
end
|
82
|
+
#
|
83
|
+
def after_all &blk
|
84
|
+
Node.hooks[:after_all]<< blk
|
85
|
+
Node.hooks[:after_all].uniq!
|
86
|
+
end
|
87
|
+
#
|
88
|
+
def error_404 node
|
89
|
+
resp = node.response
|
90
|
+
resp.status = 404
|
91
|
+
resp['Content-Type'] = 'text/plain'
|
92
|
+
resp.write "%s mapped at %p can't respond to : %p" % [ node.class.name, node.r, node.request.env['PATH_INFO'] ]
|
93
|
+
resp
|
94
|
+
end
|
95
|
+
#
|
96
|
+
end
|
97
|
+
#
|
98
|
+
attr_reader :action, :request, :response, :content
|
99
|
+
#
|
100
|
+
def initialize env, action
|
101
|
+
@env = env
|
102
|
+
@action = action
|
103
|
+
@request = Rack::Request.new env
|
104
|
+
@response = Rack::Response.new
|
105
|
+
end
|
106
|
+
#
|
107
|
+
def realize!
|
108
|
+
catch(:stop_realize) {
|
109
|
+
feed!
|
110
|
+
response.write @content
|
111
|
+
response.finish
|
112
|
+
response
|
113
|
+
}
|
114
|
+
end
|
115
|
+
#
|
116
|
+
def feed!
|
117
|
+
Node.call_before_hooks self
|
118
|
+
state :meth
|
119
|
+
@content = self.send @action[:method], *@action[:args]
|
120
|
+
v, l, e = view, layout, Config.engine_proc(@action[:engine])
|
121
|
+
# TODO compile and cache
|
122
|
+
state (@action[:layout].nil? ? :partial : :view)
|
123
|
+
@content = e.call v, self if e and File.exists? v
|
124
|
+
state :layout
|
125
|
+
@content = e.call l, self if e and File.exists? l
|
126
|
+
Node.call_after_hooks self
|
127
|
+
@content
|
128
|
+
end
|
129
|
+
#
|
130
|
+
def redirect target, options={}, &block
|
131
|
+
status = options[:status] || 302
|
132
|
+
body = options[:body] || redirect_body(target)
|
133
|
+
header = response.header.merge('Location' => target.to_s)
|
134
|
+
throw :stop_realize, Rack::Response.new(body, status, header, &block)
|
135
|
+
end
|
136
|
+
#
|
137
|
+
def redirect_body target
|
138
|
+
"You are being redirected, please follow this link to: <a href='#{target}'>#{target}</a>!"
|
139
|
+
end
|
140
|
+
#
|
141
|
+
def state state=nil
|
142
|
+
@action[:state] = state unless state.nil?
|
143
|
+
@action[:state]
|
144
|
+
end
|
145
|
+
#
|
146
|
+
def engine engine=nil
|
147
|
+
@action[:engine] = engine unless engine.nil? or engine.empty?
|
148
|
+
@action[:engine]
|
149
|
+
end
|
150
|
+
#
|
151
|
+
def layout layout=nil
|
152
|
+
@action[:layout] = layout unless layout.nil? or layout.empty?
|
153
|
+
return '' if @action[:layout].nil?
|
154
|
+
File.join(Config.layout_base_path, @action[:layout])+ Config.engine_ext(@action[:engine])
|
155
|
+
end
|
156
|
+
#
|
157
|
+
def no_layout
|
158
|
+
@action[:layout] = nil
|
159
|
+
end
|
160
|
+
#
|
161
|
+
def view view=nil
|
162
|
+
@action[:view] = view unless view.nil? or view.empty?
|
163
|
+
return '' if @action[:view].nil?
|
164
|
+
File.join(Config.view_base_path, @action[:view])+Config.engine_ext(@action[:engine])
|
165
|
+
end
|
166
|
+
#
|
167
|
+
def inherited_var sym, *args
|
168
|
+
d = self.class.inherited_vars[sym].clone || []
|
169
|
+
unless args.empty?
|
170
|
+
d.concat args
|
171
|
+
d.uniq!
|
172
|
+
end
|
173
|
+
d
|
174
|
+
end
|
175
|
+
#
|
176
|
+
def args
|
177
|
+
@action[:args]
|
178
|
+
end
|
179
|
+
#
|
180
|
+
def map
|
181
|
+
self.class.r
|
182
|
+
end
|
183
|
+
#
|
184
|
+
def r *args
|
185
|
+
File.join map, (args.empty? ? @action[:method] : args.map { |x| x.to_s } )
|
186
|
+
end
|
187
|
+
#
|
188
|
+
def html
|
189
|
+
[ :map, :r, :args, :engine, :layout, :view ].inject('') { |s,sym| s+="<p>#{sym} => #{self.send sym}</p>"; s }
|
190
|
+
end
|
191
|
+
#
|
192
|
+
end
|
193
|
+
#
|
194
|
+
end
|
195
|
+
#
|
196
|
+
# EOF
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
require 'securerandom'
|
4
|
+
#
|
5
|
+
module Zorglub
|
6
|
+
#
|
7
|
+
class Node
|
8
|
+
#
|
9
|
+
def session
|
10
|
+
@session ||= Session.new @request
|
11
|
+
end
|
12
|
+
end
|
13
|
+
#
|
14
|
+
class SessionHash
|
15
|
+
#
|
16
|
+
@data = {}
|
17
|
+
class << self
|
18
|
+
attr_reader :data
|
19
|
+
end
|
20
|
+
#
|
21
|
+
def initialize sid
|
22
|
+
@sid = sid
|
23
|
+
# TODO if sid is nil, one should be created
|
24
|
+
@session_data = SessionHash.data[sid]||={}
|
25
|
+
end
|
26
|
+
#
|
27
|
+
def exists?
|
28
|
+
not @sid.nil?
|
29
|
+
end
|
30
|
+
#
|
31
|
+
def [] idx
|
32
|
+
@session_data[idx]
|
33
|
+
end
|
34
|
+
#
|
35
|
+
def []= idx, v
|
36
|
+
@session_data[idx] = v
|
37
|
+
end
|
38
|
+
end
|
39
|
+
#
|
40
|
+
class Session
|
41
|
+
#
|
42
|
+
@session_key = 'zorglub.sid'
|
43
|
+
@session_kls = Zorglub::SessionHash
|
44
|
+
class << self
|
45
|
+
attr_accessor :session_key, :session_kls
|
46
|
+
end
|
47
|
+
#
|
48
|
+
def initialize req
|
49
|
+
@request = req
|
50
|
+
@instance = nil
|
51
|
+
end
|
52
|
+
#
|
53
|
+
def setup!
|
54
|
+
if Config.session_on
|
55
|
+
@instance = Session.session_kls.new @request.cookies[Session.session_key]
|
56
|
+
else
|
57
|
+
@instance = {}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
private :setup!
|
61
|
+
#
|
62
|
+
def exists?
|
63
|
+
setup! if @instance.nil?
|
64
|
+
@instance.exists?
|
65
|
+
end
|
66
|
+
#
|
67
|
+
def [] idx
|
68
|
+
setup! if @instance.nil?
|
69
|
+
@instance[idx]
|
70
|
+
end
|
71
|
+
#
|
72
|
+
def []= idx, v
|
73
|
+
setup! if @instance.nil?
|
74
|
+
@instance[idx] = v
|
75
|
+
end
|
76
|
+
#
|
77
|
+
end
|
78
|
+
#
|
79
|
+
end
|
80
|
+
#
|
81
|
+
# EOF
|
data/lib/zorglub.rb
ADDED
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
#
|
5
|
+
describe Zorglub do
|
6
|
+
#
|
7
|
+
describe Zorglub::App do
|
8
|
+
#
|
9
|
+
it "map should add a mapped node" do
|
10
|
+
APP.at("/temp").should be_nil
|
11
|
+
APP.map "/temp", Temp
|
12
|
+
APP.at("/temp").should be Temp
|
13
|
+
end
|
14
|
+
#
|
15
|
+
it "delete should delete a mapped node" do
|
16
|
+
APP.at("/temp").should be Temp
|
17
|
+
APP.delete "/temp"
|
18
|
+
APP.at("/temp").should be_nil
|
19
|
+
end
|
20
|
+
#
|
21
|
+
it "at should return mapped node" do
|
22
|
+
APP.at("/node1").should be Node1
|
23
|
+
end
|
24
|
+
#
|
25
|
+
it "at should return nil if no Node mapped" do
|
26
|
+
APP.at("/none").should be_nil
|
27
|
+
end
|
28
|
+
#
|
29
|
+
it "to should return path to node" do
|
30
|
+
APP.to(Node1).should == "/node1"
|
31
|
+
end
|
32
|
+
#
|
33
|
+
it "to should return nil if not an existing Node" do
|
34
|
+
APP.to(nil).should be_nil
|
35
|
+
end
|
36
|
+
#
|
37
|
+
it "to_hash should return a correct hash" do
|
38
|
+
APP.to_hash["/node1"].should be Node1
|
39
|
+
end
|
40
|
+
#
|
41
|
+
end
|
42
|
+
#
|
43
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|