rory 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73fd578d6e35268b6a7940ef886b86e1cd03f923
4
- data.tar.gz: 51731d0b123a43034399bd0c27b409dcbc898b4c
3
+ metadata.gz: 55512769abc5665735db9609c9d1dcc541b37e9f
4
+ data.tar.gz: c60a1ce6cec4f650cbfee24e77462d8461a01d8d
5
5
  SHA512:
6
- metadata.gz: 170ee5f9d5e4d1da5dc21c733d41cc26e1d8d0e12738c3edfb66739fcac09eca554019bb116b54d608f96658dcb4d3fd01b97d33acd7d9961309a1782eeb973a
7
- data.tar.gz: f02a5ae7d109c79e84cf3e28205c6a42bdf8b321520adfa9868fe8489010b8caaf513b9734b5fe06b4dcd3fd53214796141e9786a4e2e3e9e90fbaec8011fd37
6
+ metadata.gz: ce94a5c75d20071fc852dcbc71f4c887456ebe76cada4e62e96ae41c1578115229889cd00c83d7187f5e2e159d8047ede5f1d9f0bd46e988f85e76ff489eb27c
7
+ data.tar.gz: ff2b069e3e5a65f07610ecd9b32fdea59264e29e7c009f34312a9eacdfbad5217d0db62a7f37ecd1135c0219953d56c8ff2447ec713c8bf848ae2e28ba15b433
@@ -8,6 +8,7 @@ module Rory
8
8
  include PathGeneration
9
9
 
10
10
  attr_accessor :locals
11
+ attr_reader :dispatcher
11
12
 
12
13
  class << self
13
14
  def before_actions
@@ -45,6 +46,10 @@ module Rory
45
46
  @locals = {}
46
47
  end
47
48
 
49
+ def json_requested?
50
+ dispatcher.json_requested?
51
+ end
52
+
48
53
  def expose(hsh)
49
54
  locals.merge!(hsh)
50
55
  end
@@ -77,18 +82,64 @@ module Rory
77
82
  }
78
83
  end
79
84
 
80
- def render(template_name, opts = {})
85
+ def extract_options(options_or_template, opts = {})
86
+ if options_or_template.is_a?(Hash)
87
+ options_or_template
88
+ else
89
+ opts.merge(:template => options_or_template)
90
+ end
91
+ end
92
+
93
+ def set_response_defaults(opts)
94
+ opts[:content_type] ||= default_content_type
95
+ opts[:status] ||= 200
96
+ opts[:headers] = {
97
+ 'Content-type' => default_content_type,
98
+ 'charset' => 'UTF-8'
99
+ }.merge(opts[:headers] || {})
100
+ end
101
+
102
+ def render(options_or_template = nil, opts = {})
103
+ opts = extract_options(options_or_template, opts)
104
+ set_response_defaults(opts)
105
+ opts[:body] ||= generate_for_render(opts)
106
+ @response = [opts[:status], opts[:headers], [opts[:body]]]
107
+ end
108
+
109
+ def generate_json_from_object(object, opts = {})
110
+ object.to_json
111
+ end
112
+
113
+ def generate_for_render(opts = {})
114
+ object, template = opts.delete(:json), opts.delete(:template)
115
+ if object
116
+ generate_json_from_object(object, opts)
117
+ else
118
+ template ||= route_template
119
+ generate_body_from_template(template, opts)
120
+ end
121
+ end
122
+
123
+ def generate_body_from_template(template_name, opts = {})
81
124
  opts = default_renderer_options.merge(opts)
82
125
  renderer = Rory::Renderer.new(template_name, opts)
83
- @body = renderer.render
126
+ renderer.render
84
127
  end
85
128
 
86
129
  def redirect(path)
87
- @response = @dispatcher.redirect(path)
130
+ @response = dispatcher.redirect(path)
88
131
  end
89
132
 
90
133
  def render_not_found
91
- @response = @dispatcher.render_not_found
134
+ @response = dispatcher.render_not_found
135
+ end
136
+
137
+ def default_content_type
138
+ if json_requested?
139
+ 'application/json'
140
+ else
141
+ 'text/html'
142
+ end
92
143
  end
93
144
 
94
145
  def present
@@ -103,11 +154,9 @@ module Rory
103
154
  @response
104
155
  else
105
156
  # even if there wasn't a full response generated, we might already have
106
- # a @body, if render was explicitly called to render an alternate
107
- # template, or if @body was explicitly assigned for some other reason.
157
+ # a @body, if @body was explicitly assigned for some reason.
108
158
  # don't render the default template, in that case.
109
- @body ||= render(route_template)
110
- [200, {'Content-type' => 'text/html', 'charset' => 'UTF-8'}, [@body]]
159
+ render(:body => @body)
111
160
  end
112
161
  end
113
162
 
@@ -15,6 +15,34 @@ module Rory
15
15
  }
16
16
  end
17
17
 
18
+ def override_method
19
+ requested_override = request.params['_method']
20
+ return nil unless requested_override
21
+ if ['put', 'patch', 'delete'].include?(requested_override.downcase)
22
+ requested_override.downcase
23
+ end
24
+ end
25
+
26
+ def extension
27
+ File.extname(full_path)[1..-1]
28
+ end
29
+
30
+ def json_requested?
31
+ extension == 'json'
32
+ end
33
+
34
+ def full_path
35
+ @request.path_info[1..-1] || ''
36
+ end
37
+
38
+ def path_without_extension
39
+ full_path.gsub(/(.*)\.#{extension}$/, '\1')
40
+ end
41
+
42
+ def method
43
+ override_method || request.request_method.downcase
44
+ end
45
+
18
46
  def route
19
47
  @routing[:route] ||= get_route
20
48
  end
@@ -59,11 +87,11 @@ module Rory
59
87
 
60
88
  def get_route
61
89
  mapped_route = all_routes.detect do |route|
62
- route.matches_request?(@request)
90
+ route.matches_request?(path_without_extension, method)
63
91
  end
64
92
  if mapped_route
65
93
  @request.params.delete('_method')
66
- @request.params.merge! mapped_route.path_params(@request)
94
+ @request.params.merge! mapped_route.path_params(path_without_extension)
67
95
  end
68
96
  mapped_route
69
97
  end
data/lib/rory/route.rb CHANGED
@@ -28,15 +28,15 @@ module Rory
28
28
  @options[:methods] || []
29
29
  end
30
30
 
31
- def matches_request?(request)
32
- @match = regex.match(request.path_info[1..-1] || '')
31
+ def matches_request?(path, method)
32
+ @match = regex.match(path)
33
33
  @match &&
34
34
  (methods.empty? ||
35
- methods.include?(method_from_request(request).to_sym))
35
+ methods.include?(method.to_sym))
36
36
  end
37
37
 
38
- def path_params(request)
39
- @match ||= regex.match(request.path_info[1..-1] || '')
38
+ def path_params(path)
39
+ @match ||= regex.match(path)
40
40
  symbolized_param_names = @match.names.map { |name| name.to_sym }
41
41
  Hash[symbolized_param_names.zip(@match.captures)]
42
42
  end
@@ -50,17 +50,5 @@ module Rory
50
50
  :methods => @methods
51
51
  }
52
52
  end
53
-
54
- private
55
-
56
- def method_from_request(request)
57
- override_method = request.params['_method']
58
- method = if override_method && ['put', 'patch', 'delete'].include?(override_method.downcase)
59
- override_method
60
- else
61
- request.request_method
62
- end
63
- method.downcase
64
- end
65
53
  end
66
54
  end
data/lib/rory/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rory
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
  end
data/rory.gemspec CHANGED
@@ -33,7 +33,7 @@ EOF
33
33
  s.add_runtime_dependency 'thin', '~> 1.0'
34
34
 
35
35
  s.add_development_dependency 'rake'
36
- s.add_development_dependency 'rspec', '~> 2'
36
+ s.add_development_dependency 'rspec', '~> 3'
37
37
  s.add_development_dependency 'capybara'
38
38
  s.add_development_dependency 'yard'
39
39
  s.add_development_dependency 'reek'
@@ -11,5 +11,6 @@ Fixture::Application.set_routes do
11
11
  end
12
12
  match '/', :to => 'root#vegetable', :methods => [:get]
13
13
  match '/', :to => 'root#no_vegetable', :methods => [:delete]
14
+ match 'for_reals/switching', :to => 'for_reals#switching', :methods => [:get]
14
15
  match 'for_reals/:parbles', :to => 'for_reals#srsly', :methods => [:get]
15
16
  end
@@ -3,4 +3,12 @@ class ForRealsController < Rory::Controller
3
3
  expose :gibbit => @params[:parbles]
4
4
  expose :but_when => 'again'
5
5
  end
6
+
7
+ def switching
8
+ if json_requested?
9
+ render :json => { :a => 1 }
10
+ else
11
+ render 'for_reals/custom', :status => 404
12
+ end
13
+ end
6
14
  end
@@ -0,0 +1 @@
1
+ Oh, a secret!
@@ -2,15 +2,16 @@ describe Rory::Application do
2
2
  describe ".configure" do
3
3
  it 'yields the given block to self' do
4
4
  Fixture::Application.configure do |c|
5
- c.should == Fixture::Application.instance
5
+ expect(c).to eq(Fixture::Application.instance)
6
6
  end
7
7
  end
8
8
  end
9
9
 
10
10
  describe '.config_path' do
11
11
  it 'is set to {root}/config by default' do
12
- Fixture::Application.config_path.should ==
12
+ expect(Fixture::Application.config_path).to eq(
13
13
  Pathname.new(Fixture::Application.root).join('config')
14
+ )
14
15
  end
15
16
 
16
17
  it 'raises exception if root not set' do
@@ -25,14 +26,14 @@ describe Rory::Application do
25
26
 
26
27
  describe ".respond_to?" do
27
28
  it 'returns true if the instance said so' do
28
- Fixture::Application.instance.should_receive(:respond_to?).with(:goat).and_return(true)
29
- Fixture::Application.respond_to?(:goat).should be_true
29
+ expect(Fixture::Application.instance).to receive(:respond_to?).with(:goat).and_return(true)
30
+ expect(Fixture::Application.respond_to?(:goat)).to be_truthy
30
31
  end
31
32
 
32
33
  it 'does the usual thing if instance says no' do
33
- Fixture::Application.instance.should_receive(:respond_to?).twice.and_return(false)
34
- Fixture::Application.respond_to?(:to_s).should be_true
35
- Fixture::Application.respond_to?(:obviously_not_a_real_method).should be_false
34
+ expect(Fixture::Application.instance).to receive(:respond_to?).twice.and_return(false)
35
+ expect(Fixture::Application.respond_to?(:to_s)).to be_truthy
36
+ expect(Fixture::Application.respond_to?(:obviously_not_a_real_method)).to be_falsey
36
37
  end
37
38
  end
38
39
 
@@ -40,27 +41,27 @@ describe Rory::Application do
40
41
  it "forwards arg to new dispatcher, and calls dispatch" do
41
42
  dispatcher = double(:dispatch => :expected)
42
43
  rack_request = double
43
- Rack::Request.stub(:new).with(:env).and_return(rack_request)
44
- Rory::Dispatcher.should_receive(:new).with(rack_request, Fixture::Application.instance).and_return(dispatcher)
45
- Fixture::Application.call(:env).should == :expected
44
+ allow(Rack::Request).to receive(:new).with(:env).and_return(rack_request)
45
+ expect(Rory::Dispatcher).to receive(:new).with(rack_request, Fixture::Application.instance).and_return(dispatcher)
46
+ expect(Fixture::Application.call(:env)).to eq(:expected)
46
47
  end
47
48
  end
48
49
 
49
50
  describe ".load_config_data" do
50
51
  it "returns parsed yaml file with given name from directory at config_path" do
51
- Fixture::Application.any_instance.stub(:config_path).and_return('Africa the Great')
52
- YAML.stub(:load_file).with(
52
+ allow_any_instance_of(Fixture::Application).to receive(:config_path).and_return('Africa the Great')
53
+ allow(YAML).to receive(:load_file).with(
53
54
  File.expand_path(File.join('Africa the Great', 'foo_type.yml'))).
54
55
  and_return(:oscar_the_grouch_takes_a_nap)
55
- Fixture::Application.load_config_data(:foo_type).should == :oscar_the_grouch_takes_a_nap
56
+ expect(Fixture::Application.load_config_data(:foo_type)).to eq(:oscar_the_grouch_takes_a_nap)
56
57
  end
57
58
  end
58
59
 
59
60
  describe ".connect_db" do
60
61
  it "sets up sequel connection to DB from YAML file" do
61
62
  config = { 'development' => :expected }
62
- Fixture::Application.any_instance.stub(:load_config_data).with(:database).and_return(config)
63
- Sequel.should_receive(:connect).with(:expected).and_return(double(:loggers => []))
63
+ allow_any_instance_of(Fixture::Application).to receive(:load_config_data).with(:database).and_return(config)
64
+ expect(Sequel).to receive(:connect).with(:expected).and_return(double(:loggers => []))
64
65
  Fixture::Application.connect_db('development')
65
66
  end
66
67
  end
@@ -74,6 +75,7 @@ describe Rory::Application do
74
75
  Rory::Route.new('rabbits/:chew', :to => 'rabbits#chew', :methods => [:get], :module => 'goose/wombat'),
75
76
  Rory::Route.new('', :to => 'root#vegetable', :methods => [:get]),
76
77
  Rory::Route.new('', :to => 'root#no_vegetable', :methods => [:delete]),
78
+ Rory::Route.new('for_reals/switching', :to => 'for_reals#switching', :methods => [:get]),
77
79
  Rory::Route.new('for_reals/:parbles', :to => 'for_reals#srsly', :methods => [:get])
78
80
  ]
79
81
  end
@@ -81,7 +83,7 @@ describe Rory::Application do
81
83
 
82
84
  describe ".spin_up" do
83
85
  it "connects the database" do
84
- Rory::Application.any_instance.should_receive(:connect_db)
86
+ expect_any_instance_of(Rory::Application).to receive(:connect_db)
85
87
  Rory::Application.spin_up
86
88
  end
87
89
  end
@@ -92,20 +94,20 @@ describe Rory::Application do
92
94
  end
93
95
 
94
96
  it 'includes models, controllers, and helpers by default' do
95
- Fixture::Application.auto_require_paths.should == ['models', 'controllers', 'helpers']
97
+ expect(Fixture::Application.auto_require_paths).to eq(['models', 'controllers', 'helpers'])
96
98
  end
97
99
 
98
100
  it 'accepts new paths' do
99
101
  Fixture::Application.auto_require_paths << 'chocolates'
100
- Fixture::Application.auto_require_paths.should == ['models', 'controllers', 'helpers', 'chocolates']
102
+ expect(Fixture::Application.auto_require_paths).to eq(['models', 'controllers', 'helpers', 'chocolates'])
101
103
  end
102
104
  end
103
105
 
104
106
  describe '.require_all_files' do
105
107
  it 'requires all files in auto_require_paths' do
106
- Fixture::Application.any_instance.stub(:auto_require_paths).and_return(['goats', 'rhubarbs'])
108
+ allow_any_instance_of(Fixture::Application).to receive(:auto_require_paths).and_return(['goats', 'rhubarbs'])
107
109
  [:goats, :rhubarbs].each do |folder|
108
- Rory::Support.should_receive(:require_all_files_in_directory).
110
+ expect(Rory::Support).to receive(:require_all_files_in_directory).
109
111
  with(Pathname.new(Fixture::Application.root).join("#{folder}"))
110
112
  end
111
113
  Fixture::Application.require_all_files
@@ -19,7 +19,7 @@ describe Rory::Controller do
19
19
  describe '#layout' do
20
20
  it 'defaults to nil' do
21
21
  controller = Rory::Controller.new(@request, @routing)
22
- controller.layout.should be_nil
22
+ expect(controller.layout).to be_nil
23
23
  end
24
24
  end
25
25
 
@@ -35,36 +35,10 @@ describe Rory::Controller do
35
35
  end
36
36
  end
37
37
 
38
- describe "#render" do
39
- it "returns renderer output" do
40
- controller = Rory::Controller.new(@request, @routing)
41
- allow(Rory::Renderer).to receive(:new).
42
- with('not/real', controller.default_renderer_options).
43
- and_return(double('Renderer', :render => 'Here ya go'))
44
- controller.render('not/real').should == 'Here ya go'
45
- end
46
-
47
- it "passes layout, exposed locals, and app to renderer" do
48
- controller = Rory::Controller.new(@request, @routing, :scooby)
49
- controller.expose(:a => 1)
50
- allow(controller).to receive(:layout).and_return('pretend')
51
- renderer_options = {
52
- :layout => 'pretend',
53
- :locals => { :a => 1 },
54
- :app => :scooby,
55
- :base_path => 'script_root'
56
- }
57
- allow(Rory::Renderer).to receive(:new).
58
- with('also/fake', renderer_options).
59
- and_return(double('Renderer', :render => 'Scamazing!'))
60
- controller.render('also/fake').should == 'Scamazing!'
61
- end
62
- end
63
-
64
38
  describe "#redirect" do
65
39
  it "delegates to dispatcher from request" do
66
40
  @routing[:dispatcher] = dispatcher = double
67
- dispatcher.should_receive(:redirect).with(:whatever)
41
+ expect(dispatcher).to receive(:redirect).with(:whatever)
68
42
  controller = Rory::Controller.new(@request, @routing)
69
43
  controller.redirect(:whatever)
70
44
  end
@@ -73,7 +47,7 @@ describe Rory::Controller do
73
47
  describe "#render_not_found" do
74
48
  it "delegates to dispatcher from request" do
75
49
  @routing[:dispatcher] = dispatcher = double
76
- dispatcher.should_receive(:render_not_found)
50
+ expect(dispatcher).to receive(:render_not_found)
77
51
  controller = Rory::Controller.new(@request, @routing)
78
52
  controller.render_not_found
79
53
  end
@@ -122,12 +96,11 @@ describe Rory::Controller do
122
96
 
123
97
  it "doesn't try to call action from route if nonexistent on controller" do
124
98
  controller = FilteredController.new(@request, @routing)
125
- allow(controller).to receive(:respond_to?).with(:letsgo).and_return(false)
126
- expect(controller).to receive(:letsgo).never
99
+ allow(@routing[:route]).to receive(:action).and_return('no worries')
127
100
  [:pickle_something, :make_it_tasty, :rub_tummy, :sleep, :render].each do |m|
128
101
  expect(controller).to receive(m).ordered
129
102
  end
130
- controller.present
103
+ expect { controller.present }.not_to raise_error
131
104
  end
132
105
 
133
106
  it "filters before and after actions on :only and :except" do
@@ -163,27 +136,124 @@ describe Rory::Controller do
163
136
  it "just returns a response if @response exists" do
164
137
  controller = Rory::Controller.new(@request, @routing)
165
138
  controller.instance_variable_set(:@response, 'Forced response')
166
- controller.present.should == 'Forced response'
139
+ expect(controller.present).to eq('Forced response')
167
140
  end
168
141
 
169
- it "renders and returns the default template as a rack response" do
142
+ it "sends a previously set @body to render" do
170
143
  controller = Rory::Controller.new(@request, @routing)
171
- controller.present.should == [
144
+ controller.instance_variable_set(:@body, 'Forced body')
145
+ allow(controller).to receive(:render).with(:body => 'Forced body').and_return("Forced response")
146
+ expect(controller.present).to eq('Forced response')
147
+ end
148
+
149
+ it "returns the result of render" do
150
+ controller = Rory::Controller.new(@request, @routing)
151
+ allow(controller).to receive(:render).with(:body => nil).and_return("The response")
152
+ expect(controller.present).to eq('The response')
153
+ end
154
+ end
155
+
156
+ describe "#render" do
157
+ it "returns the result of #generate_body_for_render as a rack response" do
158
+ controller = Rory::Controller.new(@request, @routing)
159
+ allow(controller).to receive(:default_content_type).and_return("a prison")
160
+ allow(controller).to receive(:generate_for_render).and_return("Valoop!")
161
+ expect(controller.render).to eq([
172
162
  200,
173
- {'Content-type' => 'text/html', 'charset' => 'UTF-8'},
174
- ["Let's go content"]
175
- ]
163
+ {'Content-type' => 'a prison', 'charset' => 'UTF-8'},
164
+ ["Valoop!"]
165
+ ])
176
166
  end
177
167
 
178
- it "returns previously set @body as a rack response" do
168
+ it "returns given body as a rack response" do
179
169
  controller = Rory::Controller.new(@request, @routing)
180
- controller.instance_variable_set(:@body, 'Forced body')
181
- controller.should_receive(:render).never
182
- controller.present.should == [
170
+ allow(controller).to receive(:default_content_type).and_return("snooj/woz")
171
+ expect(controller.render(:body => 'Forced body')).to eq([
183
172
  200,
184
- {'Content-type' => 'text/html', 'charset' => 'UTF-8'},
173
+ {'Content-type' => 'snooj/woz', 'charset' => 'UTF-8'},
185
174
  ["Forced body"]
186
- ]
175
+ ])
176
+ end
177
+ end
178
+
179
+ describe "#json_requested?" do
180
+ it "delegates to dispatcher" do
181
+ controller = Rory::Controller.new(@request, @routing)
182
+ allow(controller).to receive(:dispatcher).and_return(double(:json_requested? => :snakes))
183
+ expect(controller.json_requested?).to eq(:snakes)
184
+ end
185
+ end
186
+
187
+ describe "#generate_for_render" do
188
+ it "renders and returns the default template if not json" do
189
+ controller = Rory::Controller.new(@request, @routing)
190
+ allow(controller).to receive(:generate_body_from_template).with("test/letsgo", {}).and_return("Whee")
191
+ expect(controller.generate_for_render).to eq("Whee")
192
+ end
193
+
194
+ it "renders and returns the given template if not json" do
195
+ controller = Rory::Controller.new(@request, @routing)
196
+ allow(controller).to receive(:generate_body_from_template).with("engines", {}).and_return("Oh dear")
197
+ expect(controller.generate_for_render(:template => 'engines')).to eq("Oh dear")
198
+ end
199
+
200
+ it "returns json version of given json object if json" do
201
+ controller = Rory::Controller.new(@request, @routing)
202
+ allow(controller).to receive(:generate_json_from_object).with(:an_object, {}).and_return("Oh dear")
203
+ expect(controller.generate_for_render(:json => :an_object)).to eq("Oh dear")
204
+ end
205
+ end
206
+
207
+ describe "#generate_json_from_object" do
208
+ it "returns given object as json" do
209
+ controller = Rory::Controller.new(@request, @routing)
210
+ object = double(:to_json => :jsonified)
211
+ expect(controller.generate_json_from_object(object)).to eq(:jsonified)
212
+ end
213
+ end
214
+
215
+ describe "#generate_body_from_template" do
216
+ it "returns rendered template with given name" do
217
+ controller = Rory::Controller.new(@request, @routing)
218
+ expect(controller.generate_body_from_template('test/letsgo')).to eq("Let's go content")
219
+ end
220
+
221
+ it "returns renderer output" do
222
+ controller = Rory::Controller.new(@request, @routing)
223
+ allow(Rory::Renderer).to receive(:new).
224
+ with('not/real', controller.default_renderer_options).
225
+ and_return(double('Renderer', :render => 'Here ya go'))
226
+ expect(controller.generate_body_from_template('not/real')).to eq('Here ya go')
227
+ end
228
+
229
+ it "passes layout, exposed locals, and app to renderer" do
230
+ controller = Rory::Controller.new(@request, @routing, :scooby)
231
+ controller.expose(:a => 1)
232
+ allow(controller).to receive(:layout).and_return('pretend')
233
+ renderer_options = {
234
+ :layout => 'pretend',
235
+ :locals => { :a => 1 },
236
+ :app => :scooby,
237
+ :base_path => 'script_root'
238
+ }
239
+ allow(Rory::Renderer).to receive(:new).
240
+ with('also/fake', renderer_options).
241
+ and_return(double('Renderer', :render => 'Scamazing!'))
242
+ expect(controller.generate_body_from_template('also/fake')).to eq('Scamazing!')
243
+ end
244
+ end
245
+
246
+ describe "#default_content_type" do
247
+ it "returns 'text/html' if not json" do
248
+ controller = Rory::Controller.new(@request, @routing)
249
+ allow(controller).to receive(:json_requested?).and_return(false)
250
+ expect(controller.default_content_type).to eq('text/html')
251
+ end
252
+
253
+ it "returns 'application/json' if json requested" do
254
+ controller = Rory::Controller.new(@request, @routing)
255
+ allow(controller).to receive(:json_requested?).and_return(true)
256
+ expect(controller.default_content_type).to eq('application/json')
187
257
  end
188
258
  end
189
259
  end
@@ -1,137 +1,178 @@
1
1
  describe Rory::Dispatcher do
2
+ subject { Rory::Dispatcher.new(request, Fixture::Application) }
3
+ let(:request) { {} }
4
+
5
+ describe "#extension" do
6
+ it "returns the extension of the path requested" do
7
+ allow(subject).to receive(:full_path).and_return("whatever/nerds.pickles")
8
+ expect(subject.extension).to eq("pickles")
9
+ end
10
+
11
+ it "returns nil if no extension" do
12
+ allow(subject).to receive(:full_path).and_return("whatever/nerds")
13
+ expect(subject.extension).to be_nil
14
+ end
15
+ end
16
+
17
+ describe "#path_without_extension" do
18
+ it "returns path with extension removed" do
19
+ allow(subject).to receive(:full_path).and_return("whatever/nerds.pickles")
20
+ expect(subject.path_without_extension).to eq("whatever/nerds")
21
+ end
22
+
23
+ it "returns path unchanged if no extension" do
24
+ allow(subject).to receive(:full_path).and_return("whatever/nerds")
25
+ expect(subject.path_without_extension).to eq("whatever/nerds")
26
+ end
27
+ end
28
+
29
+ describe "#json_requested?" do
30
+ it "returns true if extension is 'json'" do
31
+ allow(subject).to receive(:extension).and_return("json")
32
+ expect(subject.json_requested?).to be_truthy
33
+ end
34
+
35
+ it "returns false if extension is not 'json'" do
36
+ allow(subject).to receive(:extension).and_return("pachyderms")
37
+ expect(subject.json_requested?).to be_falsey
38
+ end
39
+ end
40
+
2
41
  describe "#redirect" do
3
42
  it "redirects to given path if path has scheme" do
4
- dispatcher = Rory::Dispatcher.new({}, Fixture::Application)
5
- redirection = dispatcher.redirect('http://example.example')
6
- redirection[0..1].should == [
43
+ redirection = subject.redirect('http://example.example')
44
+ expect(redirection[0..1]).to eq([
7
45
  302, {'Content-type' => 'text/html', 'Location'=> 'http://example.example' }
8
- ]
46
+ ])
9
47
  end
10
48
 
11
49
  it "adds request host and scheme and redirects if path has no scheme" do
12
- request = {}
13
- request.stub('scheme' => 'happy', 'host_with_port' => 'somewhere.yay')
14
- dispatcher = Rory::Dispatcher.new(request, Fixture::Application)
15
- redirection = dispatcher.redirect('/example')
16
- redirection[0..1].should == [
50
+ allow(request).to receive_messages('scheme' => 'happy', 'host_with_port' => 'somewhere.yay')
51
+ redirection = subject.redirect('/example')
52
+ expect(redirection[0..1]).to eq([
17
53
  302, {'Content-type' => 'text/html', 'Location'=> 'happy://somewhere.yay/example' }
18
- ]
54
+ ])
19
55
  end
20
56
  end
21
57
 
22
58
  describe "#dispatch" do
23
- let(:dispatcher) { Rory::Dispatcher.new(request, Fixture::Application) }
24
- let(:request) {
25
- request = { :whatever => :yay }
26
- request.stub(:path_info => '/', :request_method => 'GET', :params => {})
27
- request
28
- }
59
+ let(:request) { { :whatever => :yay } }
60
+ before(:each) do
61
+ allow(request).to receive_messages(:path_info => '/', :request_method => 'GET', :params => {})
62
+ end
29
63
 
30
64
  it "renders a 404 if the requested path is invalid" do
31
- dispatcher.stub(:get_route).and_return(nil)
32
- dispatcher.dispatch[0..1].should == [404, {"Content-type"=>"text/html"}]
65
+ allow(subject).to receive(:get_route).and_return(nil)
66
+ expect(subject.dispatch[0..1]).to eq([404, {"Content-type"=>"text/html"}])
33
67
  end
34
68
 
35
69
  it "instantiates a controller with the parsed request and calls present" do
36
70
  route = Rory::Route.new('', :to => 'stub#index')
37
- allow(dispatcher).to receive(:get_route).and_return(route)
38
- dispatcher.dispatch.should == {
71
+ allow(subject).to receive(:get_route).and_return(route)
72
+ expect(subject.dispatch).to eq({
39
73
  :whatever => :yay,
40
74
  :present_called => true # see StubController in /spec/fixture_app
41
- }
75
+ })
42
76
  end
43
77
 
44
78
  it "dispatches properly to a scoped controller" do
45
79
  route = Rory::Route.new('', :to => 'lumpies#index', :module => 'goose')
46
- allow(dispatcher).to receive(:get_route).and_return(route)
47
- dispatcher.dispatch.should == {
80
+ allow(subject).to receive(:get_route).and_return(route)
81
+ expect(subject.dispatch).to eq({
48
82
  :whatever => :yay,
49
83
  :in_scoped_controller => true # see Goose::LumpiesController in /spec/fixture_app
50
- }
84
+ })
51
85
  end
52
86
 
53
87
  it "dispatches properly to a nested scoped controller" do
54
88
  route = Rory::Route.new('', :to => 'rabbits#index', :module => 'goose/wombat')
55
- allow(dispatcher).to receive(:get_route).and_return(route)
56
- dispatcher.dispatch.should == {
89
+ allow(subject).to receive(:get_route).and_return(route)
90
+ expect(subject.dispatch).to eq({
57
91
  :whatever => :yay,
58
92
  :in_scoped_controller => true # see Goose::Wombat::RabbitsController in /spec/fixture_app
59
- }
93
+ })
60
94
  end
61
95
  end
62
96
 
63
97
  describe "#route" do
64
98
  before(:each) do
65
- @request = {}
66
- @request.stub(:params => {})
67
- @dispatcher = Rory::Dispatcher.new(@request, Fixture::Application)
99
+ allow(request).to receive_messages(:params => {})
68
100
  end
69
101
 
70
102
  it "returns route from request if already set" do
71
- @dispatcher.instance_variable_set(:@routing, { :route => 'snaky pigeons' })
72
- @dispatcher.route.should == 'snaky pigeons'
103
+ subject.instance_variable_set(:@routing, { :route => 'snaky pigeons' })
104
+ expect(subject.route).to eq('snaky pigeons')
73
105
  end
74
106
 
75
107
  it "matches the path from the request to the routes table" do
76
- @request.stub(:path_info => '/foo/3/bar', :request_method => 'GET')
77
- expect(@dispatcher.route).to eq Rory::Route.new('/foo/:id/bar', {
108
+ allow(request).to receive_messages(:path_info => '/foo/3/bar', :request_method => 'GET')
109
+ expect(subject.route).to eq Rory::Route.new('/foo/:id/bar', {
110
+ :to => 'foo#bar',
111
+ :methods => [:get, :post]
112
+ })
113
+ end
114
+
115
+ it "ignores extensions when matching path to routes table" do
116
+ allow(request).to receive_messages(:path_info => '/foo/3/bar.csv', :request_method => 'GET')
117
+ expect(subject.extension).to eq('csv')
118
+ expect(subject.route).to eq Rory::Route.new('/foo/:id/bar', {
78
119
  :to => 'foo#bar',
79
120
  :methods => [:get, :post]
80
121
  })
81
122
  end
82
123
 
83
124
  it "uses override method from params if exists" do
84
- @request.stub(:path_info => '/', :params => { '_method' => 'delete' }, :request_method => 'PUT')
85
- expect(@dispatcher.route).to eq Rory::Route.new('/', {
125
+ allow(request).to receive_messages(:path_info => '/', :params => { '_method' => 'delete' }, :request_method => 'PUT')
126
+ expect(subject.route).to eq Rory::Route.new('/', {
86
127
  :to => 'root#no_vegetable',
87
128
  :methods => [:delete]
88
129
  })
89
130
  end
90
131
 
91
132
  it "deletes override method from params" do
92
- @request.stub(:path_info => '/', :params => { '_method' => 'delete', 'goats' => 'not_sheep' }, :request_method => 'PUT')
93
- @dispatcher.route
94
- expect(@request.params).to eq('goats' => 'not_sheep')
133
+ allow(request).to receive_messages(:path_info => '/', :params => { '_method' => 'delete', 'goats' => 'not_sheep' }, :request_method => 'PUT')
134
+ subject.route
135
+ expect(request.params).to eq('goats' => 'not_sheep')
95
136
  end
96
137
 
97
138
  it "works with empty path" do
98
- @request.stub(:path_info => '', :request_method => 'GET')
99
- expect(@dispatcher.route).to eq Rory::Route.new('/', {
139
+ allow(request).to receive_messages(:path_info => '', :request_method => 'GET')
140
+ expect(subject.route).to eq Rory::Route.new('/', {
100
141
  :to => 'root#vegetable',
101
142
  :methods => [:get]
102
143
  })
103
144
  end
104
145
 
105
146
  it "works with root url represented by slash" do
106
- @request.stub(:path_info => '/', :request_method => 'GET')
107
- expect(@dispatcher.route).to eq Rory::Route.new('/', {
147
+ allow(request).to receive_messages(:path_info => '/', :request_method => 'GET')
148
+ expect(subject.route).to eq Rory::Route.new('/', {
108
149
  :to => 'root#vegetable',
109
150
  :methods => [:get]
110
151
  })
111
152
  end
112
153
 
113
154
  it "returns nil if no route found" do
114
- @request.stub(:path_info => '/umbrellas', :request_method => 'GET')
115
- @dispatcher.route.should be_nil
155
+ allow(request).to receive_messages(:path_info => '/umbrellas', :request_method => 'GET')
156
+ expect(subject.route).to be_nil
116
157
  end
117
158
 
118
159
  it "returns nil if no context" do
119
- @dispatcher = Rory::Dispatcher.new(@request)
120
- @dispatcher.route.should be_nil
160
+ subject = Rory::Dispatcher.new(request)
161
+ expect(subject.route).to be_nil
121
162
  end
122
163
 
123
164
  it "returns nil if route found but method is not allowed" do
124
- @request.stub(:path_info => '/foo', :request_method => 'GET')
125
- @dispatcher.route.should be_nil
165
+ allow(request).to receive_messages(:path_info => '/foo', :request_method => 'GET')
166
+ expect(subject.route).to be_nil
126
167
  end
127
168
 
128
169
  it "assigns named matches to params hash" do
129
- @request.stub(:path_info => '/this/some-thing_or-other/is/wicked', :request_method => 'GET')
130
- expect(@dispatcher.route).to eq Rory::Route.new('/this/:path/is/:very_awesome', {
170
+ allow(request).to receive_messages(:path_info => '/this/some-thing_or-other/is/wicked', :request_method => 'GET')
171
+ expect(subject.route).to eq Rory::Route.new('/this/:path/is/:very_awesome', {
131
172
  :to => 'awesome#rad'
132
173
  })
133
174
 
134
- @request.params.should == {:path=>"some-thing_or-other", :very_awesome=>"wicked"}
175
+ expect(request.params).to eq({:path=>"some-thing_or-other", :very_awesome=>"wicked"})
135
176
  end
136
177
  end
137
178
  end
@@ -19,7 +19,7 @@ describe Rory::Renderer::Context do
19
19
  allow(Rory::Renderer).to receive(:new).
20
20
  with('not/real', passed_renderer_options).
21
21
  and_return(double('Renderer', :render => 'Here ya go'))
22
- renderer_context.render('not/real').should == 'Here ya go'
22
+ expect(renderer_context.render('not/real')).to eq('Here ya go')
23
23
  end
24
24
 
25
25
  it "does not pass locals or layout to sub-renderer" do
@@ -35,7 +35,7 @@ describe Rory::Renderer::Context do
35
35
  allow(Rory::Renderer).to receive(:new).
36
36
  with('also/fake', passed_renderer_options).
37
37
  and_return(double('Renderer', :render => 'Scamazing!'))
38
- renderer_context.render('also/fake').should == 'Scamazing!'
38
+ expect(renderer_context.render('also/fake')).to eq('Scamazing!')
39
39
  end
40
40
  end
41
41
  end
@@ -2,33 +2,34 @@ describe Rory::Renderer do
2
2
  describe "#render" do
3
3
  it "returns text of template" do
4
4
  renderer = Rory::Renderer.new('test/static')
5
- renderer.render.should == 'Static content'
5
+ expect(renderer.render).to eq('Static content')
6
6
  end
7
7
 
8
8
  it "returns text of template in given layout" do
9
9
  controller = Rory::Renderer.new('test/static', :layout => 'surround')
10
- controller.render.should == 'Surrounding Static content is fun'
10
+ expect(controller.render).to eq('Surrounding Static content is fun')
11
11
  end
12
12
 
13
13
  it "handles symbolized layout name" do
14
14
  controller = Rory::Renderer.new('test/static', :layout => :surround)
15
- controller.render.should == 'Surrounding Static content is fun'
15
+ expect(controller.render).to eq('Surrounding Static content is fun')
16
16
  end
17
17
 
18
18
  it "exposes locals to template" do
19
19
  controller = Rory::Renderer.new('test/dynamic', :locals => { :word => 'hockey' })
20
- controller.render.should == 'Word: hockey'
20
+ expect(controller.render).to eq('Word: hockey')
21
21
  end
22
22
 
23
23
  it "can render nested templates" do
24
24
  controller = Rory::Renderer.new('test/double_nested', :locals => { :word => 'hockey' })
25
- controller.render.should ==
25
+ expect(controller.render).to eq(
26
26
  "Don't Say A Bad Word: Poop!"
27
+ )
27
28
  end
28
29
 
29
30
  it "exposes base_path to template" do
30
31
  controller = Rory::Renderer.new('test/a_link', :base_path => 'spoo')
31
- controller.render.should == 'You came from spoo.'
32
+ expect(controller.render).to eq('You came from spoo.')
32
33
  end
33
34
  end
34
35
 
@@ -36,12 +37,12 @@ describe Rory::Renderer do
36
37
  it 'returns path to template from app root' do
37
38
  fake_app = double('Application', :root => 'marbles')
38
39
  renderer = Rory::Renderer.new('goose', :app => fake_app)
39
- renderer.view_path.should == File.expand_path(File.join('views', 'goose.html.erb'), 'marbles')
40
+ expect(renderer.view_path).to eq(File.expand_path(File.join('views', 'goose.html.erb'), 'marbles'))
40
41
  end
41
42
 
42
43
  it 'uses Rory.root if no app specified' do
43
44
  renderer = Rory::Renderer.new('goose')
44
- renderer.view_path.should == File.join(Rory.root, 'views', 'goose.html.erb')
45
+ expect(renderer.view_path).to eq(File.join(Rory.root, 'views', 'goose.html.erb'))
45
46
  end
46
47
  end
47
48
  end
@@ -5,4 +5,11 @@ describe Rory::Route do
5
5
  expect(route.name).to eq 'pigeons_index'
6
6
  end
7
7
  end
8
+
9
+ describe "#path_params" do
10
+ it "extracts params from path into hash" do
11
+ route = described_class.new('/spoons/:spoon_id/forks/:fork_id', :to => 'cutlery#index')
12
+ expect(route.path_params('spoons/4/forks/yay')).to eq({ :spoon_id => "4", :fork_id => "yay" })
13
+ end
14
+ end
8
15
  end
@@ -1,20 +1,20 @@
1
1
  describe Rory::Support do
2
2
  describe ".camelize" do
3
3
  it "camelizes given snake-case string" do
4
- Rory::Support.camelize('water_under_bridge').should == 'WaterUnderBridge'
4
+ expect(Rory::Support.camelize('water_under_bridge')).to eq('WaterUnderBridge')
5
5
  end
6
6
 
7
7
  it "leaves already camel-cased string alone" do
8
- Rory::Support.camelize('OliverDrankGasoline').should == 'OliverDrankGasoline'
8
+ expect(Rory::Support.camelize('OliverDrankGasoline')).to eq('OliverDrankGasoline')
9
9
  end
10
10
  end
11
11
 
12
12
  describe '.require_all_files_in_directory' do
13
13
  it 'requires all files from given path' do
14
- Dir.stub(:[]).with(Pathname.new('spinach').join('**', '*.rb')).
14
+ allow(Dir).to receive(:[]).with(Pathname.new('spinach').join('**', '*.rb')).
15
15
  and_return(["pumpkins", "some_guy_dressed_as_liberace"])
16
- Rory::Support.should_receive(:require).with("pumpkins")
17
- Rory::Support.should_receive(:require).with("some_guy_dressed_as_liberace")
16
+ expect(Rory::Support).to receive(:require).with("pumpkins")
17
+ expect(Rory::Support).to receive(:require).with("some_guy_dressed_as_liberace")
18
18
  Rory::Support.require_all_files_in_directory('spinach')
19
19
  end
20
20
  end
@@ -31,37 +31,37 @@ describe Rory::Support do
31
31
  end
32
32
 
33
33
  it 'returns constant from camelized name' do
34
- Rory::Support.constantize('OrigamiDeliveryMan').
35
- should == OrigamiDeliveryMan
34
+ expect(Rory::Support.constantize('OrigamiDeliveryMan')).
35
+ to eq(OrigamiDeliveryMan)
36
36
  end
37
37
 
38
38
  it 'returns constant from snake-case string' do
39
- Rory::Support.constantize('origami_delivery_man').
40
- should == OrigamiDeliveryMan
39
+ expect(Rory::Support.constantize('origami_delivery_man')).
40
+ to eq(OrigamiDeliveryMan)
41
41
  end
42
42
 
43
43
  it 'returns namespaced constant' do
44
- Rory::Support.constantize(
44
+ expect(Rory::Support.constantize(
45
45
  'origami_delivery_man/under_where/skippy'
46
- ).should == OrigamiDeliveryMan::UnderWhere::Skippy
46
+ )).to eq(OrigamiDeliveryMan::UnderWhere::Skippy)
47
47
  end
48
48
  end
49
49
 
50
50
  describe '.tokenize' do
51
51
  it 'creates snake_case version of string' do
52
- described_class.tokenize('Albus Dumbledore & his_friend').should == 'albus_dumbledore_and_his_friend'
52
+ expect(described_class.tokenize('Albus Dumbledore & his_friend')).to eq('albus_dumbledore_and_his_friend')
53
53
  end
54
54
 
55
55
  it 'uncamelizes' do
56
- described_class.tokenize('thisStrangeJavalikeWord').should == 'this_strange_javalike_word'
56
+ expect(described_class.tokenize('thisStrangeJavalikeWord')).to eq('this_strange_javalike_word')
57
57
  end
58
58
 
59
59
  it 'returns nil if given nil' do
60
- described_class.tokenize(nil).should be_nil
60
+ expect(described_class.tokenize(nil)).to be_nil
61
61
  end
62
62
 
63
63
  it 'also handles symbols' do
64
- described_class.tokenize(:yourFaceIsNice).should == 'your_face_is_nice'
64
+ expect(described_class.tokenize(:yourFaceIsNice)).to eq('your_face_is_nice')
65
65
  end
66
66
  end
67
67
  end
@@ -1,13 +1,13 @@
1
1
  describe Rory do
2
2
  describe '.application' do
3
3
  it 'is by default set to the Rory::Application instance' do
4
- Rory.application.should == Fixture::Application.instance
4
+ expect(Rory.application).to eq(Fixture::Application.instance)
5
5
  end
6
6
  end
7
7
 
8
8
  describe '.root' do
9
9
  it 'returns root of application' do
10
- Rory.root.should == Rory.application.root
10
+ expect(Rory.root).to eq(Rory.application.root)
11
11
  end
12
12
  end
13
13
  end
@@ -1,9 +1,27 @@
1
1
  describe "Controller" do
2
2
  describe "presentation", :type => :feature do
3
- it 'renders action template' do
3
+ it 'renders default action template' do
4
4
  visit '/for_reals/pickles'
5
5
 
6
6
  expect(page).to have_text("You've done it again, pickles!")
7
+ expect(page.status_code).to eq 200
8
+ expect(page.response_headers['Content-Type']).to eq('text/html')
9
+ end
10
+
11
+ it 'renders json' do
12
+ visit '/for_reals/switching.json'
13
+
14
+ expect(page).to have_text({ :a => 1 }.to_json)
15
+ expect(page.status_code).to eq 200
16
+ expect(page.response_headers['Content-Type']).to eq('application/json')
17
+ end
18
+
19
+ it 'renders custom template' do
20
+ visit '/for_reals/switching'
21
+
22
+ expect(page).to have_text("Oh, a secret!")
23
+ expect(page.status_code).to eq 404
24
+ expect(page.response_headers['Content-Type']).to eq('text/html')
7
25
  end
8
26
  end
9
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ravi Gadad
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-27 00:00:00.000000000 Z
11
+ date: 2015-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '2'
75
+ version: '3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '2'
82
+ version: '3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: capybara
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +192,7 @@ files:
192
192
  - spec/fixture_app/controllers/stub_controller.rb
193
193
  - spec/fixture_app/lib/dummy_middleware.rb
194
194
  - spec/fixture_app/views/for_reals/but_wait.html.erb
195
+ - spec/fixture_app/views/for_reals/custom.html.erb
195
196
  - spec/fixture_app/views/for_reals/srsly.html.erb
196
197
  - spec/fixture_app/views/layouts/surround.html.erb
197
198
  - spec/fixture_app/views/test/a_link.html.erb