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.
@@ -0,0 +1,12 @@
1
+
2
+
3
+
4
+
5
+ module ActionTree::Errors
6
+
7
+ class NotFound < NameError
8
+ def code; 404; end
9
+ end
10
+
11
+ end
12
+
@@ -1,22 +1,24 @@
1
1
 
2
- # The scope in which matched actions are run. Used to copy instance variables, define instance variables from captures, and extend helper method modules.
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
- def initialize(*ingredients)
6
- ingredients.each do |ing|
7
- case ing
8
- when Hash
9
- ing.each do |name, value|
10
- instance_variable_set(:"@#{name}", value)
11
- end
12
- when Module
13
- extend ing
14
- else
15
- ing.instance_variables.each do |name|
16
- self.instance_variable_set(name,
17
- ing.instance_variable_get(name)
18
- )
19
- end
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.descend(location).should == 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.descend('/the')
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.descend('/the/world')
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.descend('/the')
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.descend('/the').should == subject.descend('/the')
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.descend('/the/world/is').should == subject.descend('/the/world/is')
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.descend('/the/world/is/good')
37
+ n = subject.locate('/the/world/is/good')
43
38
  n.token.should == 'good'
44
- n.should == subject.descend('the').descend('world/is').descend('good')
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::Match do
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 'no values when no match' do
29
- subject.match('/one/two/three/bobsleigh').run.should be_nil
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
- not_found { 'nix nada zip' }
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
- not_found('a/b') { @v5 + h4 }
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
- '123456'
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.descend('houses')
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.descend('houses/create')
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.descend('houses/:id')
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.descend('houses/:id/edit')
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.descend([/[0-9]+/])
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.descend(['houses', :id, /[0-9]+/])
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::Dialect
6
+ extend ActionTree::Basic
7
7
  class Node < ActionTree::Basic::Node; end
8
- class Match < ActionTree::Basic::Match; end
9
- apply(ActionTree::Plugins::Tilt)
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
- - 1
8
- - 1
9
- version: 0.1.1
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-02-02 00:00:00 +01:00
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
- description: ActionTree is a router. It provides a compact DSL for defining routes that map paths to actions. It was designed as a router for modern ruby mini-frameworks.
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/match.rb
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/dialect_helper.rb
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
- - lib/action_tree/plugins/tilt.rb
60
- - spec/01_support_lib_spec.rb
61
- - spec/02_node_spec.rb
62
- - spec/03_match_spec.rb
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 routing dry enough to kill cacti.
144
+ summary: Versatile and DRY controllers and routing.
100
145
  test_files:
101
- - spec/01_support_lib_spec.rb
102
- - spec/02_node_spec.rb
103
- - spec/03_match_spec.rb
104
- - spec/04_integration_spec.rb
105
- - spec/p01_tilt_spec.rb
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