lego-core 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -52,7 +52,7 @@ It's all about the bits an pieces!
52
52
 
53
53
  module Matcher
54
54
  def self.match_route(route, env)
55
- (route[:path] == env['PATH_INFO']) ? true : false
55
+ (route[:path] == env['PATH_INFO']) ? [env, {}] : false
56
56
  end
57
57
  end
58
58
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -14,7 +14,7 @@ module BasicRoutes
14
14
 
15
15
  module RouteMatcher
16
16
  def self.match_route(route, env)
17
- (route[:path] == env['PATH_INFO']) ? true : false
17
+ (route[:path] == env['PATH_INFO']) ? [env, {}] : false
18
18
  end
19
19
  end
20
20
  end
@@ -26,8 +26,9 @@ module RegexpMatcher
26
26
 
27
27
  def self.match_route(route, env)
28
28
  if route[:path].is_a?(Regexp) && match = route[:path].match(env['PATH_INFO'])
29
- route[:instance_vars] = { :caps => match.captures }
30
- true
29
+ match_data = {}
30
+ match_data[:instance_vars] = { :caps => match.captures }
31
+ [env, match_data]
31
32
  else
32
33
  false
33
34
  end
@@ -45,11 +46,12 @@ module SymbolExtractor
45
46
  if matches.size > 0
46
47
  exp = Regexp.escape( route[:path] ).gsub(/:([\w]+)/, "([\\w]+)")
47
48
  if match = Regexp.new("^#{exp}$").match(env["PATH_INFO"])
48
- route[:instance_vars] = {} if route[:instance_vars].nil?
49
+ match_data = {}
50
+ match_data[:instance_vars] = {}
49
51
  1.upto(matches.size) do |i|
50
- route[:instance_vars][matches[i-1]] = match.captures[i-1]
52
+ match_data[:instance_vars][matches[i-1]] = match.captures[i-1]
51
53
  end
52
- return true
54
+ return [env, match_data]
53
55
  end
54
56
  end
55
57
  false
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'lego-modules'
3
+ require 'lego-core'
4
+ require 'erb'
5
+
6
+ # Global options
7
+ Lego.config do
8
+ plugin SimpleRouter
9
+ set :views => "./"
10
+ end
11
+
12
+ class MyApp < Lego::Controller
13
+
14
+ # Load our Erb plugin for this controller.
15
+ plugin ViewHelpers
16
+
17
+ get '/' do
18
+ redirect_to '/hello'
19
+ end
20
+
21
+ get '/hello' do
22
+ # Setup a instance var for our template to use...
23
+ @title = "Hello, right now it's:"
24
+ # Render our ERB template hello.erb found in the templates folder.
25
+ @userinput = "<b>hello bold</b>"
26
+ erb :hello
27
+ end
28
+
29
+ end
30
+
31
+ # Makes Rack run our app
32
+ run MyApp
@@ -0,0 +1,5 @@
1
+ <%= h1 @title %>
2
+
3
+ <p><%= Time.new %></p>
4
+
5
+ <p>...and here is some user input: <%=h @userinput %></p>
@@ -0,0 +1,47 @@
1
+ module SimpleRouter
2
+ def self.register(lego)
3
+ lego.add_plugin :router, RouteMatcher
4
+ lego.add_plugin :controller, RouteHandler
5
+ end
6
+
7
+ module RouteHandler
8
+ def get(path, &block)
9
+ add_route(:get, {:path => path, :action_block => block})
10
+ end
11
+ end
12
+
13
+ module RouteMatcher
14
+ def self.match_route(route, env)
15
+ (route[:path] == env['PATH_INFO']) ? [env, {}] : false
16
+ end
17
+ end
18
+ end
19
+
20
+ module ViewHelpers
21
+ def self.register(lego)
22
+ lego.add_plugin :view, View
23
+ end
24
+
25
+ module View
26
+ def redirect_to(path)
27
+ @response[:code] = 301
28
+ @response[:headers].merge!({'Location', path})
29
+ ""
30
+ end
31
+
32
+ def h1(content)
33
+ "<h1>#{content}</h1>"
34
+ end
35
+
36
+ def h(s)
37
+ html_escape = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
38
+ s.to_s.gsub(/[&"><]/) { |special| html_escape[special] }
39
+ end
40
+
41
+ def erb(template, bind = binding)
42
+ path = options(:views) || "#{File.dirname(__file__)/views}"
43
+ template = File.read("#{path}/#{template}.erb") if template.is_a? Symbol
44
+ ERB.new(template).result(bind)
45
+ end
46
+ end
47
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{lego-core}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mathias Stjernstr\303\266m", "Patrik Hedman"]
12
- s.date = %q{2010-01-12}
12
+ s.date = %q{2010-01-13}
13
13
  s.description = %q{It's all about the bits and peices}
14
14
  s.email = %q{mathias@globalinn.com}
15
15
  s.extra_rdoc_files = [
@@ -21,6 +21,9 @@ Gem::Specification.new do |s|
21
21
  "Rakefile",
22
22
  "VERSION",
23
23
  "examples/config.ru",
24
+ "examples/sample_with_plugins/config.ru",
25
+ "examples/sample_with_plugins/hello.erb",
26
+ "examples/sample_with_plugins/lego-modules.rb",
24
27
  "lego-core.gemspec",
25
28
  "lib/lego-core.rb",
26
29
  "lib/lego/controller.rb",
@@ -54,7 +57,8 @@ Gem::Specification.new do |s|
54
57
  "spec/lego/plugin/controller/not_found_spec.rb",
55
58
  "spec/lego/plugin_spec.rb",
56
59
  "spec/lego_spec.rb",
57
- "spec/spec_helper.rb"
60
+ "spec/spec_helper.rb",
61
+ "examples/sample_with_plugins/lego-modules.rb"
58
62
  ]
59
63
 
60
64
  if s.respond_to? :specification_version then
@@ -140,11 +140,11 @@ class Lego::Controller
140
140
  #
141
141
 
142
142
  def call(env)
143
- if route = self::RouteHandler.match_all_routes(env)
144
- self::ActionContext.new.run(route, env)
143
+ if match_data = self::RouteHandler.match_all_routes(env)
144
+ self::ActionContext.new.run(match_data)
145
145
  else
146
146
  if route = self::RouteHandler.routes[:not_found]
147
- self::ActionContext.new.run(route, env)
147
+ self::ActionContext.new.run([route, env, { :set_response_code => 404 }])
148
148
  else
149
149
  [404, {'Content-Type' => 'text/html'}, '404 - Not found']
150
150
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  class Lego::Controller::ActionContext
5
5
 
6
- attr_accessor :response, :env, :route
6
+ attr_accessor :response, :env, :route, :match_data
7
7
 
8
8
  def initialize
9
9
  setup_defaults
@@ -13,9 +13,8 @@ class Lego::Controller::ActionContext
13
13
  "#{self.class::ApplicationClass.current_config.options(key)}"
14
14
  end
15
15
 
16
- def run(route, env)
17
- @route = route
18
- @env = env
16
+ def run(match_data)
17
+ @route, @env, @match_data = match_data
19
18
  setup_instance_vars_from_route
20
19
  evaluate_action
21
20
  [@response[:code], @response[:headers], @response[:body]]
@@ -29,10 +28,10 @@ private
29
28
  #
30
29
 
31
30
  def setup_instance_vars_from_route
32
- @route[:instance_vars].each_key do |var|
33
- instance_variable_set("@#{var}", @route[:instance_vars][var])
34
- end if @route[:instance_vars]
35
- @response[:code] = @route[:set_response_code] if @route[:set_response_code]
31
+ @match_data[:instance_vars].each_key do |var|
32
+ instance_variable_set("@#{var}", @match_data[:instance_vars][var])
33
+ end if @match_data[:instance_vars]
34
+ @response[:code] = @match_data[:set_response_code] if @match_data[:set_response_code]
36
35
  end
37
36
 
38
37
  #
@@ -16,7 +16,6 @@ module Lego::Controller::RouteHandler
16
16
 
17
17
  def extended(base)
18
18
  base.matchers.concat(matchers)
19
- base.routes.merge!(routes)
20
19
  end
21
20
 
22
21
  def add_route(method, options)
@@ -50,7 +49,8 @@ module Lego::Controller::RouteHandler
50
49
 
51
50
  def run_matchers(route, env)
52
51
  matchers.each do |matcher|
53
- return true if matcher.match_route(route, env) == true
52
+ match = matcher.match_route(route, env)
53
+ return match if match.kind_of?(Array)
54
54
  end
55
55
  false
56
56
  end
@@ -58,7 +58,9 @@ module Lego::Controller::RouteHandler
58
58
  def match_all_routes(env)
59
59
  method = extract_method_from_env(env)
60
60
  routes[method].each do |route|
61
- return route if run_matchers(route, env)
61
+ if match_data = run_matchers(route, env)
62
+ return [route] | match_data
63
+ end
62
64
  end
63
65
  nil
64
66
  end
@@ -48,7 +48,8 @@ describe 'Full stack request' do
48
48
  end
49
49
  module Matcher
50
50
  def self.match_route(route, env)
51
- (route[:path] == env['PATH_INFO']) ? true : false
51
+ match_data = { :instance_vars => { :foo => "bar" }}
52
+ (route[:path] == env['PATH_INFO']) ? [env, match_data] : false
52
53
  end
53
54
  end
54
55
  end
@@ -57,7 +58,7 @@ describe 'Full stack request' do
57
58
 
58
59
  class App1 < Lego::Controller
59
60
  get '/hello' do
60
- h1 'Hello world'
61
+ h1 "Hello world, #{@foo}"
61
62
  end
62
63
  end
63
64
 
@@ -71,7 +72,7 @@ describe 'Full stack request' do
71
72
  it 'should respond with with valid data' do
72
73
  @result[0].should eql(200)
73
74
  @result[1].should eql({"Content-Type"=>"text/html"})
74
- @result[2].should eql('<h1>Hello world</h1>')
75
+ @result[2].should eql('<h1>Hello world, bar</h1>')
75
76
  end
76
77
 
77
78
  after do
@@ -9,17 +9,17 @@ describe Lego::Controller::ActionContext do
9
9
 
10
10
  it 'should set the current message body' do
11
11
  @instance.response[:body] = "Hello again"
12
- @instance.run({},nil).should eql([ 200, {"Content-Type"=>"text/html"}, 'Hello again' ])
12
+ @instance.run([{},nil, {}]).should eql([ 200, {"Content-Type"=>"text/html"}, 'Hello again' ])
13
13
  end
14
14
 
15
15
  it 'should set response headers' do
16
16
  @instance.response[:headers] = {'Content-Type' => 'cust/head'}
17
- @instance.run({},nil).should eql([ 200, {"Content-Type"=>"cust/head"}, '' ])
17
+ @instance.run([{},nil, {}]).should eql([ 200, {"Content-Type"=>"cust/head"}, '' ])
18
18
  end
19
19
 
20
20
  it 'should set response code' do
21
21
  @instance.response[:code] = 666
22
- @instance.run({},nil).should eql([ 666, {"Content-Type"=>"text/html"}, '' ])
22
+ @instance.run([{},nil,{}]).should eql([ 666, {"Content-Type"=>"text/html"}, '' ])
23
23
  end
24
24
  end
25
25
 
@@ -30,23 +30,25 @@ describe Lego::Controller::ActionContext do
30
30
  end
31
31
 
32
32
  it 'should have a default Rack response' do
33
- @instance.run("", @env).should eql([200, {'Content-Type' => 'text/html'} , ''])
33
+ @instance.run(["", @env, {}]).should eql([200, {'Content-Type' => 'text/html'} , ''])
34
34
  end
35
35
 
36
36
  it 'should evaluate :action_block in instance if exists in route' do
37
37
  route = { :action_block => Proc.new{ "Hello my world!" }}
38
- @instance.run(route, @env).should eql([200, {'Content-Type' => 'text/html'} , "Hello my world!" ])
38
+ @instance.run([route, @env, {}]).should eql([200, {'Content-Type' => 'text/html'} , "Hello my world!" ])
39
39
  end
40
40
 
41
41
  it 'should convert route[:instance_vars] to instance variables' do
42
- route = { :instance_vars => { :myvar => "This is my var" } }
43
- @instance.run(route, @env).should eql([200, {'Content-Type' => 'text/html'} , '' ])
42
+ route = {}
43
+ match_data = { :instance_vars => { :myvar => "This is my var" } }
44
+ @instance.run([route, @env, match_data]).should eql([200, {'Content-Type' => 'text/html'} , '' ])
44
45
  @instance.instance_variable_get(:@myvar).should eql("This is my var")
45
46
  end
46
47
 
47
48
  it 'should set response[:code] if set_response_route is set in route' do
48
- route = { :set_response_code => 666 }
49
- @instance.run(route, @env).should eql([666, {'Content-Type' => 'text/html'} , '' ])
49
+ route = {}
50
+ route_match = { :set_response_code => 666 }
51
+ @instance.run([route, @env, route_match]).should eql([666, {'Content-Type' => 'text/html'} , '' ])
50
52
  end
51
53
  end
52
54
 
@@ -61,7 +63,7 @@ describe Lego::Controller::ActionContext do
61
63
  it 'should evaluate :action_block in instance if exists in route' do
62
64
  Lego::Controller.set :foo => "bar"
63
65
  route = { :action_block => Proc.new{ options(:foo) }}
64
- @instance.run(route, @env).should eql([200, {'Content-Type' => 'text/html'} , "bar" ])
66
+ @instance.run([route, @env, {}]).should eql([200, {'Content-Type' => 'text/html'} , "bar" ])
65
67
  end
66
68
 
67
69
  after do
@@ -12,11 +12,11 @@ describe Lego::Controller::RouteHandler do
12
12
  @fake_routes = {:get => [@other_route, @other_route, @valid_route], :post => [{}]}
13
13
  end
14
14
 
15
- it 'should return matching route if found' do
15
+ it 'should return Array matching route found' do
16
16
  @route_handler.should_receive(:routes).and_return(@fake_routes)
17
17
  @route_handler.should_receive(:run_matchers).with(@other_route, @env).exactly(2).times.and_return(false)
18
- @route_handler.should_receive(:run_matchers).with(@valid_route, @env).and_return(true)
19
- @route_handler.match_all_routes(@env).should eql(@valid_route)
18
+ @route_handler.should_receive(:run_matchers).with(@valid_route, @env).and_return([@env, [:var => "some var"]])
19
+ @route_handler.match_all_routes(@env).should eql( [@valid_route, @env, [:var => "some var"]] )
20
20
  end
21
21
 
22
22
  it 'should return false when no matching route is found' do
@@ -36,11 +36,11 @@ describe Lego::Controller::RouteHandler do
36
36
  @matchers = [Match1, Match2]
37
37
  end
38
38
 
39
- it 'should return true when matching route found' do
39
+ it 'should return Array when matching route found' do
40
40
  Match1.should_receive(:match_route).with(@route, @env).and_return(false)
41
- Match2.should_receive(:match_route).with(@route, @env).and_return(true)
41
+ Match2.should_receive(:match_route).with(@route, @env).and_return([@env, { :var => "a var"}])
42
42
  @route_handler.should_receive(:matchers).and_return(@matchers)
43
- @route_handler.run_matchers(@route, @env).should eql(true)
43
+ @route_handler.run_matchers(@route, @env).should eql([@env, { :var => "a var"}])
44
44
  end
45
45
 
46
46
  it 'should return false when no matching route found' do
@@ -88,6 +88,38 @@ describe Lego::Controller::RouteHandler do
88
88
  end
89
89
  end
90
90
 
91
+ context '.add_route with global plugins' do
92
+ before do
93
+ module RouterPlugin
94
+ reset_lego_base
95
+ def self.register(lego)
96
+ lego.add_plugin(:controller, self)
97
+ end
98
+ def get(path)
99
+ add_route(:get, {:path => path})
100
+ end
101
+ end
102
+ Lego.plugin RouterPlugin
103
+
104
+ class App1 < Lego::Controller
105
+ get('/app1')
106
+ end
107
+
108
+ class App2 < Lego::Controller
109
+ get('/app2')
110
+ end
111
+ end
112
+
113
+ it 'should not share routes between apps' do
114
+ App1::RouteHandler.routes[:get].should eql([:path => "/app1"])
115
+ App2::RouteHandler.routes[:get].should eql([:path => "/app2"])
116
+ end
117
+
118
+ after do
119
+ rm_const 'App1', 'App2'
120
+ end
121
+ end
122
+
91
123
  context '.matchers' do
92
124
  before do
93
125
  @route_handler = empty_route_handler
@@ -165,13 +165,15 @@ describe Lego::Controller do
165
165
  context 'with a route that matches' do
166
166
  before do
167
167
  @env = ["Environment"]
168
+ @match_data = [:foo => "bar"]
169
+ @match_route = [:route => "route"]
168
170
  create_new_app("MyApp", Lego::Controller)
169
- MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return("route")
171
+ MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return([@match_route, @env, @match_data])
170
172
  end
171
173
 
172
174
  it 'should create a new instance of ActionContext' do
173
175
  mock = mock("ActionContext instance")
174
- mock.should_receive(:run).with("route", @env)
176
+ mock.should_receive(:run).with([@match_route, @env, @match_data])
175
177
  MyApp::ActionContext.should_receive(:new).and_return(mock)
176
178
  end
177
179
 
@@ -181,45 +183,45 @@ describe Lego::Controller do
181
183
  end
182
184
  end
183
185
 
184
- context 'with a route that don\'t matches' do
186
+ context 'without a route match and a not_found route defined' do
185
187
  before do
186
- @env = ["Environment"]
188
+ @env = []
189
+ @block = lambda { "404, gone." }
187
190
  create_new_app("MyApp", Lego::Controller)
188
191
  MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return(nil)
192
+ MyApp::RouteHandler.should_receive('routes').and_return({:not_found => { :action_block => @block }})
189
193
  end
190
194
 
191
- it 'should create a new instance of ActionContext' do
192
- MyApp::ActionContext.should_not_receive(:new)
195
+ it 'should get a valid 404 response with the block data' do
196
+ MyApp.call(@env).should eql(
197
+ [404, {'Content-Type' => 'text/html'}, '404, gone.']
198
+ )
193
199
  end
194
200
 
195
201
  after do
196
- MyApp.call(@env).should eql(
197
- [404, {'Content-Type' => 'text/html'}, '404 - Not found']
198
- )
199
202
  rm_const "MyApp"
200
203
  end
201
204
  end
202
205
 
203
- context 'without matching route and a :not_found route defined' do
206
+ context 'with a route that don\'t matches' do
204
207
  before do
205
- @env = ["Rack Env"]
206
- @routes = { :not_found => {}}
208
+ @env = ["Environment"]
207
209
  create_new_app("MyApp", Lego::Controller)
208
210
  MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return(nil)
209
- MyApp::RouteHandler.should_receive(:routes).and_return( @routes )
210
211
  end
211
212
 
212
- it 'should create a new ActionContext with the :not_found route' do
213
- action_context = mock("ActionContext instance")
214
- MyApp::ActionContext.should_receive(:new).and_return(action_context)
215
- action_context.should_receive(:run).with(@routes[:not_found], @env)
213
+ it 'should create a new instance of ActionContext' do
214
+ MyApp::ActionContext.should_not_receive(:new)
216
215
  end
217
216
 
218
217
  after do
219
- MyApp.call(@env)
218
+ MyApp.call(@env).should eql(
219
+ [404, {'Content-Type' => 'text/html'}, '404 - Not found']
220
+ )
220
221
  rm_const "MyApp"
221
222
  end
222
223
  end
224
+
223
225
  end
224
226
 
225
227
  context ".set" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lego-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Mathias Stjernstr\xC3\xB6m"
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2010-01-12 00:00:00 +01:00
13
+ date: 2010-01-13 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -28,6 +28,9 @@ files:
28
28
  - Rakefile
29
29
  - VERSION
30
30
  - examples/config.ru
31
+ - examples/sample_with_plugins/config.ru
32
+ - examples/sample_with_plugins/hello.erb
33
+ - examples/sample_with_plugins/lego-modules.rb
31
34
  - lego-core.gemspec
32
35
  - lib/lego-core.rb
33
36
  - lib/lego/controller.rb
@@ -84,3 +87,4 @@ test_files:
84
87
  - spec/lego/plugin_spec.rb
85
88
  - spec/lego_spec.rb
86
89
  - spec/spec_helper.rb
90
+ - examples/sample_with_plugins/lego-modules.rb