action_tree 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -5
- data/README.md +6 -77
- data/Rakefile +16 -3
- data/TODO +84 -26
- data/VERSION +1 -1
- data/lib/action_tree.rb +46 -27
- data/lib/action_tree/basic.rb +36 -0
- data/lib/action_tree/basic/helpers.rb +20 -0
- data/lib/action_tree/basic/node.rb +294 -103
- data/lib/action_tree/basic/query.rb +211 -0
- data/lib/action_tree/basic/shared.rb +25 -0
- data/lib/action_tree/capture_hash.rb +28 -3
- data/lib/action_tree/components/rack.rb +52 -0
- data/lib/action_tree/components/rack/request.rb +59 -0
- data/lib/action_tree/components/rack/response.rb +10 -0
- data/lib/action_tree/components/tilt.rb +65 -0
- data/lib/action_tree/errors.rb +12 -0
- data/lib/action_tree/eval_scope.rb +18 -16
- data/spec/00_foundations/capture_hash_spec.rb +47 -0
- data/spec/00_foundations/eval_scope_spec.rb +80 -0
- data/spec/{02_node_spec.rb → 01_node/02_node_spec.rb} +8 -13
- data/spec/{03_match_spec.rb → 02_query/query_spec.rb} +5 -4
- data/spec/{04_integration_spec.rb → 03_action_tree_basic/04_integration_spec.rb} +10 -8
- data/spec/{p01_tilt_spec.rb → 04_components/template_spec.rb} +5 -9
- metadata +66 -20
- data/MANUAL.md +0 -277
- data/lib/action_tree/basic/match.rb +0 -132
- data/lib/action_tree/dialect_helper.rb +0 -12
- data/lib/action_tree/plugins/tilt.rb +0 -65
- data/spec/01_support_lib_spec.rb +0 -41
@@ -1,22 +1,24 @@
|
|
1
1
|
|
2
|
-
# The scope
|
2
|
+
# The execution scope for running matches. Built dynamically for each match by mixing in modules and setting variables.
|
3
|
+
# @api private
|
3
4
|
|
4
5
|
class ActionTree::EvalScope
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
6
|
+
|
7
|
+
# Build a new EvalScope from the given sources. The
|
8
|
+
# sources can be:
|
9
|
+
#
|
10
|
+
# * Hash: instance variable names and values (:name becomes @name)
|
11
|
+
# * Module: will be extended
|
12
|
+
# * Array: flattened and used just the same
|
13
|
+
#
|
14
|
+
def initialize(*sources)
|
15
|
+
Array(sources).flatten.each do |s|
|
16
|
+
case s
|
17
|
+
when Hash
|
18
|
+
s.each {|k,v| instance_variable_set(:"@#{k}", v) }
|
19
|
+
when Module then extend s
|
20
|
+
else
|
21
|
+
raise 'invalid scope source ' + s.inspect
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
require 'action_tree'
|
3
|
+
|
4
|
+
|
5
|
+
EXTRA_FAMILY_INFO = {
|
6
|
+
:brother => 'Smerdyakov',
|
7
|
+
:father => 'Fyodor'
|
8
|
+
}
|
9
|
+
|
10
|
+
describe ActionTree::CaptureHash do
|
11
|
+
|
12
|
+
describe '#add' do
|
13
|
+
it 'once adds item as itself' do
|
14
|
+
subject.add :canoe_color, 'green'
|
15
|
+
subject[:canoe_color].should == 'green'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'more than once becomes an Array' do
|
19
|
+
subject.add :sister, 'Arleta'
|
20
|
+
subject.add :sister, 'Maud'
|
21
|
+
subject[:sister].should == ['Arleta', 'Maud']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#merge' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
subject.add :brother, 'Dmitry'
|
29
|
+
subject.add :brother, 'Ivan'
|
30
|
+
subject.add :brother, 'Alexey'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'merges with array, accumulating on equal keys' do
|
34
|
+
family = subject.merge(EXTRA_FAMILY_INFO)
|
35
|
+
family[:brother].should ==
|
36
|
+
%w{Dmitry Ivan Alexey Smerdyakov}
|
37
|
+
family[:father].should == 'Fyodor'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'is non-destructive' do
|
41
|
+
family = subject.dup
|
42
|
+
family.merge(EXTRA_FAMILY_INFO)
|
43
|
+
family.should == subject
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
require 'action_tree'
|
3
|
+
|
4
|
+
module Hooga
|
5
|
+
def peace
|
6
|
+
'is valuable'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Booga
|
11
|
+
def get_name
|
12
|
+
'Melchior'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Shooga
|
17
|
+
def get_name
|
18
|
+
'Baltazar'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
LIFE_MEMO = {
|
23
|
+
:love => :free,
|
24
|
+
:world => :good
|
25
|
+
}
|
26
|
+
|
27
|
+
DEATH_MEMO = {
|
28
|
+
:world => :over,
|
29
|
+
:worries => :none
|
30
|
+
}
|
31
|
+
|
32
|
+
describe ActionTree::EvalScope do
|
33
|
+
|
34
|
+
describe 'when created' do
|
35
|
+
|
36
|
+
subject do
|
37
|
+
ActionTree::EvalScope.new(
|
38
|
+
Hooga, Booga, LIFE_MEMO
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'sets instance variables given a hash' do
|
43
|
+
LIFE_MEMO.each do |k,v|
|
44
|
+
subject.instance_eval("@#{k.to_s}").should == v
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'given a module, extends it' do
|
49
|
+
subject.get_name.should == 'Melchior'
|
50
|
+
subject.peace.should == 'is valuable'
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'prioritizes' do
|
56
|
+
|
57
|
+
subject do
|
58
|
+
ActionTree::EvalScope.new(
|
59
|
+
[[Hooga], Booga, Shooga],
|
60
|
+
[LIFE_MEMO, DEATH_MEMO]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'and recursively reads arrays' do
|
65
|
+
subject.peace.should == 'is valuable'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'latest variables over first' do
|
69
|
+
LIFE_MEMO.merge(DEATH_MEMO).each do |k,v|
|
70
|
+
subject.instance_eval("@#{k.to_s}").should == v
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'latest extensions over first' do
|
75
|
+
subject.get_name.should == 'Baltazar'
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -3,45 +3,40 @@ require 'action_tree'
|
|
3
3
|
|
4
4
|
describe ActionTree::Basic::Node do
|
5
5
|
|
6
|
-
|
7
6
|
# PATH PARSING AND DESCENDING
|
8
7
|
|
9
|
-
it 'can be inspected' do
|
10
|
-
subject.inspect
|
11
|
-
end
|
12
|
-
|
13
8
|
describe 'descend' do
|
14
9
|
it 'returns self when descending to nil, "", "/" or []' do
|
15
10
|
[nil, '', '/', []].each do |location|
|
16
|
-
subject.
|
11
|
+
subject.locate(location).should == subject
|
17
12
|
end
|
18
13
|
end
|
19
14
|
|
20
15
|
it 'returns a new node when descending one level' do
|
21
|
-
n = subject.
|
16
|
+
n = subject.locate('/the')
|
22
17
|
n.should be_a(ActionTree::Basic::Node)
|
23
18
|
n.should_not == subject
|
24
19
|
end
|
25
20
|
|
26
21
|
it 'returns a new node when descending two levels' do
|
27
|
-
n = subject.
|
22
|
+
n = subject.locate('/the/world')
|
28
23
|
n.should be_a(ActionTree::Basic::Node)
|
29
24
|
n.should_not == subject
|
30
|
-
n.should_not == subject.
|
25
|
+
n.should_not == subject.locate('/the')
|
31
26
|
end
|
32
27
|
|
33
28
|
it 'gives same node when descending two times, one level' do
|
34
|
-
subject.
|
29
|
+
subject.locate('/the').should == subject.locate('/the')
|
35
30
|
end
|
36
31
|
|
37
32
|
it 'gives same node when descending two times, three levels' do
|
38
|
-
subject.
|
33
|
+
subject.locate('/the/world/is').should == subject.locate('/the/world/is')
|
39
34
|
end
|
40
35
|
|
41
36
|
it 'gives birth recursively and selectively when descending' do
|
42
|
-
n = subject.
|
37
|
+
n = subject.locate('/the/world/is/good')
|
43
38
|
n.token.should == 'good'
|
44
|
-
n.should == subject.
|
39
|
+
n.should == subject.locate('the').locate('world/is').locate('good')
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -5,7 +5,7 @@ require 'action_tree'
|
|
5
5
|
|
6
6
|
|
7
7
|
|
8
|
-
describe ActionTree::Basic::
|
8
|
+
describe ActionTree::Basic::Query do
|
9
9
|
|
10
10
|
it 'can be inspected' do
|
11
11
|
ActionTree.new.match.inspect
|
@@ -25,8 +25,9 @@ describe ActionTree::Basic::Match do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
it '
|
29
|
-
subject.match('/one/two/three/bobsleigh').run.
|
28
|
+
it 'raises NotFound when no match' do
|
29
|
+
expect { subject.match('/one/two/three/bobsleigh').run }.
|
30
|
+
to raise_error(ActionTree::NotFound)
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'one value' do
|
@@ -54,7 +55,7 @@ describe ActionTree::Basic::Match do
|
|
54
55
|
after { @boring = false }
|
55
56
|
action { "no sound at #{@altitude} altitudes" }
|
56
57
|
helpers { def infinite?; true; end }
|
57
|
-
|
58
|
+
handle(NotFound) { 'nix nada zip' }
|
58
59
|
route :world do
|
59
60
|
before { @status = :threatened }
|
60
61
|
helpers { def infinite?; false; end }
|
@@ -25,7 +25,9 @@ describe ActionTree do
|
|
25
25
|
before('/a/b') { @v4 = @v3 + '5' }
|
26
26
|
before('/a/b') { @v5 = @v4 }
|
27
27
|
a('/a/b') { @v5 }
|
28
|
-
|
28
|
+
route('a/b') do
|
29
|
+
handle(NotFound) { 'not_found' }
|
30
|
+
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -39,7 +41,7 @@ describe ActionTree do
|
|
39
41
|
|
40
42
|
it 'works with not_found' do
|
41
43
|
subject.match('a/b/y').run.should ==
|
42
|
-
'
|
44
|
+
'not_found'
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
@@ -88,19 +90,19 @@ describe ActionTree do
|
|
88
90
|
end
|
89
91
|
|
90
92
|
it 'matches a first level request' do
|
91
|
-
subject.match('/houses').node.should == subject.
|
93
|
+
subject.match('/houses').node.should == subject.locate('houses')
|
92
94
|
end
|
93
95
|
|
94
96
|
it 'matches a second level request' do
|
95
|
-
subject.match('/houses/create').node.should == subject.
|
97
|
+
subject.match('/houses/create').node.should == subject.locate('houses/create')
|
96
98
|
end
|
97
99
|
|
98
100
|
it 'matches a second level capture' do
|
99
|
-
subject.match('/houses/4').node.should == subject.
|
101
|
+
subject.match('/houses/4').node.should == subject.locate('houses/:id')
|
100
102
|
end
|
101
103
|
|
102
104
|
it 'matches beneath second level capture' do
|
103
|
-
subject.match('/houses/4/edit').node.should == subject.
|
105
|
+
subject.match('/houses/4/edit').node.should == subject.locate('houses/:id/edit')
|
104
106
|
end
|
105
107
|
|
106
108
|
it 'returns nil for nonexistant node beneath capture' do
|
@@ -121,7 +123,7 @@ describe ActionTree do
|
|
121
123
|
end
|
122
124
|
|
123
125
|
it 'matches regexp in root scope' do
|
124
|
-
subject.match('/346').node.should == subject.
|
126
|
+
subject.match('/346').node.should == subject.locate([/[0-9]+/])
|
125
127
|
end
|
126
128
|
|
127
129
|
it 'fills in path for regexp in root scope' do
|
@@ -129,7 +131,7 @@ describe ActionTree do
|
|
129
131
|
end
|
130
132
|
|
131
133
|
it 'matches regexp in capture scope' do
|
132
|
-
subject.match('/houses/5/4').node.should == subject.
|
134
|
+
subject.match('/houses/5/4').node.should == subject.locate(['houses', :id, /[0-9]+/])
|
133
135
|
end
|
134
136
|
|
135
137
|
it 'fills in path for regexp in capture scope' do
|
@@ -3,13 +3,14 @@ require 'action_tree'
|
|
3
3
|
require 'haml'
|
4
4
|
|
5
5
|
module Templated
|
6
|
-
extend ActionTree::
|
6
|
+
extend ActionTree::Basic
|
7
7
|
class Node < ActionTree::Basic::Node; end
|
8
|
-
class
|
9
|
-
|
8
|
+
class Query < ActionTree::Basic::Query; end
|
9
|
+
#use ActionTree::Components::Templating
|
10
10
|
end
|
11
11
|
|
12
12
|
|
13
|
+
=begin
|
13
14
|
describe Templated::Node do
|
14
15
|
|
15
16
|
pending 'still passes normal specs'
|
@@ -51,10 +52,5 @@ describe Templated::Node do
|
|
51
52
|
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
=end
|
60
56
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- jbe
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-03-28 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,46 @@ dependencies:
|
|
30
30
|
version: "0"
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
|
-
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: yard
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: yard-rspec
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id004
|
72
|
+
description: ActionTree is a DRY request router. It provides a compact DSL for defining actions and mapping requests to invoke them.
|
34
73
|
email: post@jostein.be
|
35
74
|
executables: []
|
36
75
|
|
@@ -45,26 +84,32 @@ files:
|
|
45
84
|
- .rspec
|
46
85
|
- .yardopts
|
47
86
|
- LICENSE
|
48
|
-
- MANUAL.md
|
49
87
|
- README.md
|
50
88
|
- Rakefile
|
51
89
|
- TODO
|
52
90
|
- VERSION
|
53
91
|
- lib/action_tree.rb
|
54
|
-
- lib/action_tree/basic
|
92
|
+
- lib/action_tree/basic.rb
|
93
|
+
- lib/action_tree/basic/helpers.rb
|
55
94
|
- lib/action_tree/basic/node.rb
|
95
|
+
- lib/action_tree/basic/query.rb
|
96
|
+
- lib/action_tree/basic/shared.rb
|
56
97
|
- lib/action_tree/capture_hash.rb
|
57
|
-
- lib/action_tree/
|
98
|
+
- lib/action_tree/components/rack.rb
|
99
|
+
- lib/action_tree/components/rack/request.rb
|
100
|
+
- lib/action_tree/components/rack/response.rb
|
101
|
+
- lib/action_tree/components/tilt.rb
|
102
|
+
- lib/action_tree/errors.rb
|
58
103
|
- lib/action_tree/eval_scope.rb
|
59
|
-
-
|
60
|
-
- spec/
|
61
|
-
- spec/02_node_spec.rb
|
62
|
-
- spec/
|
63
|
-
- spec/04_integration_spec.rb
|
104
|
+
- spec/00_foundations/capture_hash_spec.rb
|
105
|
+
- spec/00_foundations/eval_scope_spec.rb
|
106
|
+
- spec/01_node/02_node_spec.rb
|
107
|
+
- spec/02_query/query_spec.rb
|
108
|
+
- spec/03_action_tree_basic/04_integration_spec.rb
|
109
|
+
- spec/04_components/template_spec.rb
|
64
110
|
- spec/fixtures/test.haml
|
65
111
|
- spec/fixtures/test_layout.haml
|
66
112
|
- spec/log
|
67
|
-
- spec/p01_tilt_spec.rb
|
68
113
|
has_rdoc: true
|
69
114
|
homepage: http://github.com/jbe/action_tree
|
70
115
|
licenses: []
|
@@ -96,10 +141,11 @@ rubyforge_project:
|
|
96
141
|
rubygems_version: 1.3.7
|
97
142
|
signing_key:
|
98
143
|
specification_version: 3
|
99
|
-
summary: Versatile
|
144
|
+
summary: Versatile and DRY controllers and routing.
|
100
145
|
test_files:
|
101
|
-
- spec/
|
102
|
-
- spec/
|
103
|
-
- spec/
|
104
|
-
- spec/
|
105
|
-
- spec/
|
146
|
+
- spec/00_foundations/capture_hash_spec.rb
|
147
|
+
- spec/00_foundations/eval_scope_spec.rb
|
148
|
+
- spec/01_node/02_node_spec.rb
|
149
|
+
- spec/02_query/query_spec.rb
|
150
|
+
- spec/03_action_tree_basic/04_integration_spec.rb
|
151
|
+
- spec/04_components/template_spec.rb
|