rory 0.4.1 → 0.5.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.
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