action_tree 0.1.1 → 0.2.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.
@@ -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