merb-core 0.9.5 → 0.9.6
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.
- data/CHANGELOG +925 -0
- data/CONTRIBUTORS +93 -0
- data/PUBLIC_CHANGELOG +85 -0
- data/Rakefile +18 -28
- data/bin/merb +34 -5
- data/lib/merb-core/autoload.rb +2 -3
- data/lib/merb-core/bootloader.rb +60 -66
- data/lib/merb-core/config.rb +7 -1
- data/lib/merb-core/controller/abstract_controller.rb +35 -21
- data/lib/merb-core/controller/merb_controller.rb +15 -42
- data/lib/merb-core/controller/mixins/authentication.rb +42 -6
- data/lib/merb-core/controller/mixins/conditional_get.rb +83 -0
- data/lib/merb-core/controller/mixins/render.rb +3 -3
- data/lib/merb-core/core_ext/kernel.rb +6 -19
- data/lib/merb-core/dispatch/cookies.rb +96 -80
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +2 -0
- data/lib/merb-core/dispatch/request.rb +18 -16
- data/lib/merb-core/dispatch/router/route.rb +6 -0
- data/lib/merb-core/dispatch/router.rb +4 -1
- data/lib/merb-core/dispatch/session/container.rb +64 -0
- data/lib/merb-core/dispatch/session/cookie.rb +91 -101
- data/lib/merb-core/dispatch/session/memcached.rb +38 -174
- data/lib/merb-core/dispatch/session/memory.rb +62 -208
- data/lib/merb-core/dispatch/session/store_container.rb +145 -0
- data/lib/merb-core/dispatch/session.rb +174 -48
- data/lib/merb-core/rack/middleware/conditional_get.rb +14 -8
- data/lib/merb-core/rack/middleware/csrf.rb +73 -0
- data/lib/merb-core/rack.rb +1 -0
- data/lib/merb-core/script.rb +112 -0
- data/lib/merb-core/server.rb +2 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +25 -0
- data/lib/merb-core/test/helpers/request_helper.rb +40 -3
- data/lib/merb-core/test/run_specs.rb +4 -3
- data/lib/merb-core/vendor/facets/inflect.rb +7 -10
- data/lib/merb-core/version.rb +1 -1
- data/lib/merb-core.rb +11 -40
- data/spec/private/core_ext/kernel_spec.rb +0 -11
- data/spec/private/dispatch/fixture/log/merb_test.log +893 -0
- data/spec/private/router/fixture/log/merb_test.log +12 -1728
- data/spec/private/router/route_spec.rb +4 -0
- data/spec/private/router/router_spec.rb +8 -0
- data/spec/private/vendor/facets/plural_spec.rb +1 -1
- data/spec/private/vendor/facets/singular_spec.rb +1 -1
- data/spec/public/abstract_controller/controllers/display.rb +8 -2
- data/spec/public/abstract_controller/controllers/filters.rb +18 -0
- data/spec/public/abstract_controller/display_spec.rb +6 -2
- data/spec/public/abstract_controller/filter_spec.rb +4 -0
- data/spec/public/controller/authentication_spec.rb +114 -43
- data/spec/public/controller/base_spec.rb +8 -0
- data/spec/public/controller/conditional_get_spec.rb +100 -0
- data/spec/public/controller/config/init.rb +1 -1
- data/spec/public/controller/controllers/authentication.rb +29 -0
- data/spec/public/controller/controllers/base.rb +13 -0
- data/spec/public/controller/controllers/conditional_get.rb +35 -0
- data/spec/public/controller/controllers/cookies.rb +10 -1
- data/spec/public/controller/cookies_spec.rb +38 -9
- data/spec/public/controller/spec_helper.rb +1 -0
- data/spec/public/controller/url_spec.rb +70 -1
- data/spec/public/directory_structure/directory/log/merb_test.log +461 -0
- data/spec/public/rack/conditinal_get_middleware_spec.rb +77 -89
- data/spec/public/rack/csrf_middleware_spec.rb +70 -0
- data/spec/public/reloading/directory/log/merb_test.log +52 -0
- data/spec/public/request/request_spec.rb +19 -1
- data/spec/public/router/fixation_spec.rb +26 -4
- data/spec/public/router/fixture/log/merb_test.log +234 -30332
- data/spec/public/session/controllers/sessions.rb +52 -0
- data/spec/public/session/cookie_session_spec.rb +73 -0
- data/spec/public/session/memcached_session_spec.rb +31 -0
- data/spec/public/session/memory_session_spec.rb +28 -0
- data/spec/public/session/multiple_sessions_spec.rb +74 -0
- data/spec/public/session/no_session_spec.rb +12 -0
- data/spec/public/session/session_spec.rb +91 -0
- data/spec/public/test/controllers/spec_helper_controller.rb +2 -1
- data/spec/public/test/request_helper_spec.rb +15 -0
- data/spec/spec_helper.rb +2 -2
- metadata +23 -5
- data/spec/private/dispatch/cookies_spec.rb +0 -219
- data/spec/private/dispatch/session_mixin_spec.rb +0 -47
@@ -27,7 +27,7 @@
|
|
27
27
|
# before :some_filter
|
28
28
|
# before :authenticate, :exclude => [:login, :signup]
|
29
29
|
# before :has_role, :with => ["Admin"], :exclude => [:index, :show]
|
30
|
-
# before Proc.new {
|
30
|
+
# before Proc.new { some_method }, :only => :foo
|
31
31
|
# before :authorize, :unless => :logged_in?
|
32
32
|
#
|
33
33
|
# You can use either <code>:only => :actionname</code> or
|
@@ -64,8 +64,8 @@
|
|
64
64
|
# If the second arg is a Proc, it will be called and its return
|
65
65
|
# value will be what is rendered to the browser:
|
66
66
|
#
|
67
|
-
# throw :halt, proc {
|
68
|
-
# throw :halt, proc {
|
67
|
+
# throw :halt, proc { access_denied }
|
68
|
+
# throw :halt, proc { Tidy.new(c.index) }
|
69
69
|
#
|
70
70
|
# ===== Filter Options (.before, .after, .add_filter, .if, .unless)
|
71
71
|
# :only<Symbol, Array[Symbol]>::
|
@@ -98,6 +98,7 @@ class Merb::AbstractController
|
|
98
98
|
|
99
99
|
class_inheritable_accessor :_layout, :_template_root, :template_roots
|
100
100
|
class_inheritable_accessor :_before_filters, :_after_filters
|
101
|
+
class_inheritable_accessor :_before_dispatch_callbacks, :_after_dispatch_callbacks
|
101
102
|
|
102
103
|
cattr_accessor :_abstract_subclasses
|
103
104
|
|
@@ -113,6 +114,7 @@ class Merb::AbstractController
|
|
113
114
|
FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
|
114
115
|
|
115
116
|
self._before_filters, self._after_filters = [], []
|
117
|
+
self._before_dispatch_callbacks, self._after_dispatch_callbacks = [], []
|
116
118
|
|
117
119
|
#---
|
118
120
|
# We're using abstract_subclasses so that Merb::Controller can have its
|
@@ -217,7 +219,7 @@ class Merb::AbstractController
|
|
217
219
|
include Object.full_const_get("#{helper_module_name}") rescue nil
|
218
220
|
HERE
|
219
221
|
super
|
220
|
-
end
|
222
|
+
end
|
221
223
|
end
|
222
224
|
|
223
225
|
# ==== Parameters
|
@@ -228,7 +230,7 @@ class Merb::AbstractController
|
|
228
230
|
@_template_stack = []
|
229
231
|
end
|
230
232
|
|
231
|
-
# This will dispatch the request, calling
|
233
|
+
# This will dispatch the request, calling internal before/after dispatch_callbacks
|
232
234
|
#
|
233
235
|
# ==== Parameters
|
234
236
|
# action<~to_s>::
|
@@ -238,7 +240,7 @@ class Merb::AbstractController
|
|
238
240
|
# ==== Raises
|
239
241
|
# MerbControllerError:: Invalid body content caught.
|
240
242
|
def _dispatch(action)
|
241
|
-
|
243
|
+
self._before_dispatch_callbacks.each { |cb| cb.call(self) }
|
242
244
|
self.action_name = action
|
243
245
|
|
244
246
|
caught = catch(:halt) do
|
@@ -253,14 +255,16 @@ class Merb::AbstractController
|
|
253
255
|
when String then caught
|
254
256
|
when nil then _filters_halted
|
255
257
|
when Symbol then __send__(caught)
|
256
|
-
when Proc then
|
258
|
+
when Proc then self.instance_eval(&caught)
|
257
259
|
else
|
258
260
|
raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
|
259
261
|
end
|
260
262
|
start = Time.now
|
261
263
|
_call_filters(_after_filters)
|
262
264
|
@_benchmarks[:after_filters_time] = Time.now - start if _after_filters
|
263
|
-
|
265
|
+
|
266
|
+
self._after_dispatch_callbacks.each { |cb| cb.call(self) }
|
267
|
+
|
264
268
|
@body
|
265
269
|
end
|
266
270
|
|
@@ -298,7 +302,7 @@ class Merb::AbstractController
|
|
298
302
|
else
|
299
303
|
send(filter)
|
300
304
|
end
|
301
|
-
when Proc
|
305
|
+
when Proc then self.instance_eval(&filter)
|
302
306
|
end
|
303
307
|
end
|
304
308
|
end
|
@@ -360,7 +364,7 @@ class Merb::AbstractController
|
|
360
364
|
def _evaluate_condition(condition)
|
361
365
|
case condition
|
362
366
|
when Symbol : self.send(condition)
|
363
|
-
when Proc :
|
367
|
+
when Proc : self.instance_eval(&condition)
|
364
368
|
else
|
365
369
|
raise ArgumentError,
|
366
370
|
'Filter condtions need to be either a Symbol or a Proc'
|
@@ -412,14 +416,6 @@ class Merb::AbstractController
|
|
412
416
|
#---
|
413
417
|
# Defaults that can be overridden by plugins, other mixins, or subclasses
|
414
418
|
def _filters_halted() "<html><body><h1>Filter Chain Halted!</h1></body></html>" end
|
415
|
-
|
416
|
-
# Method stub for setting up the session. This will be overriden by session
|
417
|
-
# modules.
|
418
|
-
def setup_session() end
|
419
|
-
|
420
|
-
# Method stub for finalizing up the session. This will be overriden by
|
421
|
-
# session modules.
|
422
|
-
def finalize_session() end
|
423
419
|
|
424
420
|
# ==== Parameters
|
425
421
|
# name<~to_sym, Hash>:: The name of the URL to generate.
|
@@ -453,11 +449,24 @@ class Merb::AbstractController
|
|
453
449
|
# ==== Returns
|
454
450
|
# String:: The generated url with protocol + hostname + URL.
|
455
451
|
#
|
452
|
+
# ==== Options
|
453
|
+
#
|
454
|
+
# :protocol and :host options are special: use them to explicitly
|
455
|
+
# specify protocol and host of resulting url. If you omit them,
|
456
|
+
# protocol and host of request are used.
|
457
|
+
#
|
456
458
|
# ==== Alternatives
|
457
459
|
# If a hash is used as the first argument, a default route will be
|
458
460
|
# generated based on it and rparams.
|
459
461
|
def absolute_url(name, rparams={})
|
460
|
-
|
462
|
+
# FIXME: arrgh, why request.protocol returns http://?
|
463
|
+
# :// is not part of protocol name
|
464
|
+
protocol = rparams.delete(:protocol)
|
465
|
+
protocol << "://" if protocol
|
466
|
+
|
467
|
+
(protocol || request.protocol) +
|
468
|
+
(rparams.delete(:host) || request.host) +
|
469
|
+
url(name, rparams)
|
461
470
|
end
|
462
471
|
|
463
472
|
# Calls the capture method for the selected template engine.
|
@@ -506,9 +515,14 @@ class Merb::AbstractController
|
|
506
515
|
end
|
507
516
|
|
508
517
|
opts = normalize_filters!(opts)
|
509
|
-
|
518
|
+
|
510
519
|
case filter
|
511
|
-
when
|
520
|
+
when Proc
|
521
|
+
# filters with procs created via class methods have identical signature
|
522
|
+
# regardless if they handle content differently or not. So procs just
|
523
|
+
# get appended
|
524
|
+
filters << [filter, opts]
|
525
|
+
when Symbol, String
|
512
526
|
if existing_filter = filters.find {|f| f.first.to_s[filter.to_s]}
|
513
527
|
filters[ filters.index(existing_filter) ] = [filter, opts]
|
514
528
|
else
|
@@ -1,24 +1,19 @@
|
|
1
1
|
class Merb::Controller < Merb::AbstractController
|
2
2
|
|
3
|
-
class_inheritable_accessor :_hidden_actions, :_shown_actions
|
4
|
-
:_session_id_key, :_session_secret_key, :_session_expiry, :_session_cookie_domain
|
3
|
+
class_inheritable_accessor :_hidden_actions, :_shown_actions
|
5
4
|
|
6
5
|
self._hidden_actions ||= []
|
7
|
-
self._shown_actions
|
8
|
-
|
6
|
+
self._shown_actions ||= []
|
7
|
+
|
9
8
|
cattr_accessor :_subclasses
|
10
9
|
self._subclasses = Set.new
|
11
10
|
|
12
11
|
def self.subclasses_list() _subclasses end
|
13
12
|
|
14
|
-
self._session_secret_key = nil
|
15
|
-
self._session_id_key = Merb::Config[:session_id_key] || '_session_id'
|
16
|
-
self._session_expiry = Merb::Config[:session_expiry] || Merb::Const::WEEK * 2
|
17
|
-
self._session_cookie_domain = Merb::Config[:session_cookie_domain]
|
18
|
-
|
19
13
|
include Merb::ResponderMixin
|
20
14
|
include Merb::ControllerMixin
|
21
15
|
include Merb::AuthenticationMixin
|
16
|
+
include Merb::ConditionalGetMixin
|
22
17
|
|
23
18
|
class << self
|
24
19
|
|
@@ -102,7 +97,7 @@ class Merb::Controller < Merb::AbstractController
|
|
102
97
|
end
|
103
98
|
|
104
99
|
private
|
105
|
-
|
100
|
+
|
106
101
|
# All methods that are callable as actions.
|
107
102
|
#
|
108
103
|
# ==== Returns
|
@@ -140,15 +135,15 @@ class Merb::Controller < Merb::AbstractController
|
|
140
135
|
def _template_location(context, type, controller)
|
141
136
|
_conditionally_append_extension(controller ? "#{controller}/#{context}" : "#{context}", type)
|
142
137
|
end
|
143
|
-
|
144
|
-
# The location to look for a template and mime-type. This is overridden
|
145
|
-
# from AbstractController, which defines a version of this that does not
|
138
|
+
|
139
|
+
# The location to look for a template and mime-type. This is overridden
|
140
|
+
# from AbstractController, which defines a version of this that does not
|
146
141
|
# involve mime-types.
|
147
142
|
#
|
148
143
|
# ==== Parameters
|
149
|
-
# template<String>::
|
144
|
+
# template<String>::
|
150
145
|
# The absolute path to a template - without mime and template extension.
|
151
|
-
# The mime-type extension is optional - it will be appended from the
|
146
|
+
# The mime-type extension is optional - it will be appended from the
|
152
147
|
# current content type if it hasn't been added already.
|
153
148
|
# type<~to_s>::
|
154
149
|
# The mime-type of the template that will be rendered. Defaults to nil.
|
@@ -163,11 +158,8 @@ class Merb::Controller < Merb::AbstractController
|
|
163
158
|
# Sets the variables that came in through the dispatch as available to
|
164
159
|
# the controller.
|
165
160
|
#
|
166
|
-
# This method uses the :session_id_cookie_only and :query_string_whitelist
|
167
|
-
# configuration options. See CONFIG for more details.
|
168
|
-
#
|
169
161
|
# ==== Parameters
|
170
|
-
# request<Merb::Request>:: The Merb::Request that came in from
|
162
|
+
# request<Merb::Request>:: The Merb::Request that came in from Rack.
|
171
163
|
# status<Integer>:: An integer code for the status. Defaults to 200.
|
172
164
|
# headers<Hash{header => value}>::
|
173
165
|
# A hash of headers to start the controller with. These headers can be
|
@@ -204,7 +196,7 @@ class Merb::Controller < Merb::AbstractController
|
|
204
196
|
end
|
205
197
|
|
206
198
|
attr_reader :request, :headers
|
207
|
-
|
199
|
+
|
208
200
|
def status
|
209
201
|
@_status
|
210
202
|
end
|
@@ -227,20 +219,6 @@ class Merb::Controller < Merb::AbstractController
|
|
227
219
|
# Hash:: The parameters from the request object
|
228
220
|
def params() request.params end
|
229
221
|
|
230
|
-
# ==== Returns
|
231
|
-
# Merb::Cookies::
|
232
|
-
# A new Merb::Cookies instance representing the cookies that came in
|
233
|
-
# from the request object
|
234
|
-
#
|
235
|
-
# ==== Notes
|
236
|
-
# Headers are passed into the cookie object so that you can do:
|
237
|
-
# cookies[:foo] = "bar"
|
238
|
-
def cookies() @_cookies ||= _setup_cookies end
|
239
|
-
|
240
|
-
# ==== Returns
|
241
|
-
# Hash:: The session that was extracted from the request object.
|
242
|
-
def session() request.session end
|
243
|
-
|
244
222
|
# The results of the controller's render, to be returned to Rack.
|
245
223
|
#
|
246
224
|
# ==== Returns
|
@@ -249,19 +227,14 @@ class Merb::Controller < Merb::AbstractController
|
|
249
227
|
def rack_response
|
250
228
|
[status, headers, body]
|
251
229
|
end
|
252
|
-
|
230
|
+
|
253
231
|
# Hide any methods that may have been exposed as actions before.
|
254
232
|
hide_action(*_callable_methods)
|
255
|
-
|
233
|
+
|
256
234
|
private
|
257
235
|
|
258
236
|
# If not already added, add the proper mime extension to the template path.
|
259
237
|
def _conditionally_append_extension(template, type)
|
260
238
|
type && !template.match(/\.#{type.to_s.escape_regexp}$/) ? "#{template}.#{type}" : template
|
261
239
|
end
|
262
|
-
|
263
|
-
# Create a default cookie jar, and pre-set a fixation cookie if fixation is enabled.
|
264
|
-
def _setup_cookies
|
265
|
-
::Merb::Cookies.new(request.cookies, @headers)
|
266
|
-
end
|
267
|
-
end
|
240
|
+
end
|
@@ -45,10 +45,27 @@ module Merb::AuthenticationMixin
|
|
45
45
|
#
|
46
46
|
# end
|
47
47
|
#
|
48
|
+
# If you need to request basic authentication inside an action you need to use the request! method.
|
49
|
+
#
|
50
|
+
# ====Example
|
51
|
+
#
|
52
|
+
# class Sessions < Application
|
53
|
+
#
|
54
|
+
# def new
|
55
|
+
# case content_type
|
56
|
+
# when :html
|
57
|
+
# render
|
58
|
+
# else
|
59
|
+
# basic_authentication.request!
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# end
|
64
|
+
#
|
48
65
|
#---
|
49
66
|
# @public
|
50
67
|
def basic_authentication(realm = "Application", &authenticator)
|
51
|
-
BasicAuthentication.new(self, realm, &authenticator)
|
68
|
+
@_basic_authentication ||= BasicAuthentication.new(self, realm, &authenticator)
|
52
69
|
end
|
53
70
|
|
54
71
|
class BasicAuthentication
|
@@ -58,24 +75,43 @@ module Merb::AuthenticationMixin
|
|
58
75
|
def initialize(controller, realm = "Application", &authenticator)
|
59
76
|
@controller = controller
|
60
77
|
@realm = realm
|
78
|
+
@auth = Rack::Auth::Basic::Request.new(@controller.request.env)
|
61
79
|
authenticate_or_request(&authenticator) if authenticator
|
62
80
|
end
|
63
81
|
|
64
82
|
def authenticate(&authenticator)
|
65
|
-
auth
|
66
|
-
|
67
|
-
if auth.provided? and auth.basic?
|
68
|
-
authenticator.call(*auth.credentials)
|
83
|
+
if @auth.provided? and @auth.basic?
|
84
|
+
authenticator.call(*@auth.credentials)
|
69
85
|
else
|
70
86
|
false
|
71
87
|
end
|
72
88
|
end
|
73
89
|
|
74
90
|
def request
|
75
|
-
|
91
|
+
request!
|
76
92
|
throw :halt, @controller.render("HTTP Basic: Access denied.\n", :status => Unauthorized.status, :layout => false)
|
77
93
|
end
|
78
94
|
|
95
|
+
# This is a special case for use outside a before filter. Use this if you need to
|
96
|
+
# request basic authenticaiton as part of an action
|
97
|
+
def request!
|
98
|
+
@controller.status = Unauthorized.status
|
99
|
+
@controller.headers['WWW-Authenticate'] = 'Basic realm="%s"' % @realm
|
100
|
+
end
|
101
|
+
|
102
|
+
# Checks to see if there has been any basic authentication credentials provided
|
103
|
+
def provided?
|
104
|
+
@auth.provided?
|
105
|
+
end
|
106
|
+
|
107
|
+
def username
|
108
|
+
provided? ? @auth.credentials.first : nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def password
|
112
|
+
provided? ? @auth.credentials.last : nil
|
113
|
+
end
|
114
|
+
|
79
115
|
protected
|
80
116
|
|
81
117
|
def authenticate_or_request(&authenticator)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Provides conditional get support in Merb core.
|
2
|
+
# Conditional get support is intentionally
|
3
|
+
# simple and does not do fancy stuff like making
|
4
|
+
# ETag value from Ruby objects for you.
|
5
|
+
#
|
6
|
+
# The most interesting method for end user is
|
7
|
+
# +request_fresh?+ that is used after setting of
|
8
|
+
# last modification time or ETag:
|
9
|
+
#
|
10
|
+
# ==== Example
|
11
|
+
#
|
12
|
+
# def show
|
13
|
+
# self.etag = Digest::SHA1.hexdigest(calculate_cache_key(params))
|
14
|
+
#
|
15
|
+
# if request_fresh?
|
16
|
+
# self.status = 304
|
17
|
+
# return ''
|
18
|
+
# else
|
19
|
+
# @product = Product.get(params[:id])
|
20
|
+
# display @product
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
module Merb::ConditionalGetMixin
|
24
|
+
|
25
|
+
# Sets ETag response header by calling
|
26
|
+
# #to_s on the argument.
|
27
|
+
#
|
28
|
+
# ==== Parameters
|
29
|
+
# tag<~to_s>::
|
30
|
+
# value of ETag header enclosed in double quotes
|
31
|
+
# as required by the RFC
|
32
|
+
def etag=(tag)
|
33
|
+
headers[Merb::Const::ETAG] = %("#{tag}")
|
34
|
+
end
|
35
|
+
|
36
|
+
# ==== Returns
|
37
|
+
# <String>::
|
38
|
+
# Value of ETag response header or nil if it's not set.
|
39
|
+
def etag
|
40
|
+
headers[Merb::Const::ETAG]
|
41
|
+
end
|
42
|
+
|
43
|
+
# ==== Returns
|
44
|
+
# <Boolean>::
|
45
|
+
# true if ETag response header equals If-None-Match request header,
|
46
|
+
# false otherwise
|
47
|
+
def etag_matches?(tag = self.etag)
|
48
|
+
tag == self.request.if_none_match
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets Last-Modified response header.
|
52
|
+
#
|
53
|
+
# ==== Parameters
|
54
|
+
# tag<Time>::
|
55
|
+
# resource modification timestamp converted into format
|
56
|
+
# required by the RFC
|
57
|
+
def last_modified=(time)
|
58
|
+
headers[Merb::Const::LAST_MODIFIED] = time.httpdate
|
59
|
+
end
|
60
|
+
|
61
|
+
# ==== Returns
|
62
|
+
# <String>::
|
63
|
+
# Value of Last-Modified response header or nil if it's not set.
|
64
|
+
def last_modified
|
65
|
+
Time.rfc2822(headers[Merb::Const::LAST_MODIFIED])
|
66
|
+
end
|
67
|
+
|
68
|
+
# ==== Returns
|
69
|
+
# <Boolean>::
|
70
|
+
# true if Last-Modified response header is < than
|
71
|
+
# If-Modified-Since request header value, false otherwise.
|
72
|
+
def not_modified?(time = self.last_modified)
|
73
|
+
request.if_modified_since && time && time <= request.if_modified_since
|
74
|
+
end
|
75
|
+
|
76
|
+
# ==== Returns
|
77
|
+
# <Boolean>::
|
78
|
+
# true if either ETag matches or entity is not modified,
|
79
|
+
# so request is fresh; false otherwise
|
80
|
+
def request_fresh?
|
81
|
+
etag_matches?(self.etag) || not_modified?(self.last_modified)
|
82
|
+
end
|
83
|
+
end
|
@@ -41,7 +41,7 @@ module Merb::RenderMixin
|
|
41
41
|
# ==== Returns
|
42
42
|
# Hash:: The default render options.
|
43
43
|
def layout(layout)
|
44
|
-
self.default_render_options.update(:layout => (layout
|
44
|
+
self.default_render_options.update(:layout => (layout || false))
|
45
45
|
end
|
46
46
|
|
47
47
|
# Enable the default layout logic - reset the layout option.
|
@@ -95,7 +95,7 @@ module Merb::RenderMixin
|
|
95
95
|
thing ||= action_name.to_sym
|
96
96
|
|
97
97
|
# Content negotiation
|
98
|
-
|
98
|
+
self.content_type = opts[:format] if opts[:format]
|
99
99
|
|
100
100
|
# Handle options (:status)
|
101
101
|
_handle_options!(opts)
|
@@ -189,7 +189,7 @@ module Merb::RenderMixin
|
|
189
189
|
# explicitly passed in the opts.
|
190
190
|
#
|
191
191
|
def display(object, thing = nil, opts = {})
|
192
|
-
template_opt = opts.delete(:template)
|
192
|
+
template_opt = thing.is_a?(Hash) ? thing.delete(:template) : opts.delete(:template)
|
193
193
|
|
194
194
|
case thing
|
195
195
|
# display @object, "path/to/foo" means display @object, nil, :template => "path/to/foo"
|
@@ -37,27 +37,14 @@ module Kernel
|
|
37
37
|
# If the gem cannot be found, the method will attempt to require the string
|
38
38
|
# as a library.
|
39
39
|
def load_dependency(name, *ver)
|
40
|
-
try_framework = Merb.frozen?
|
41
40
|
begin
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if name =~ /^merb/ && try_framework
|
46
|
-
require name
|
47
|
-
else
|
48
|
-
gem(name, *ver) if ver
|
49
|
-
require name
|
50
|
-
Merb.logger.info!("loading gem '#{name}' ...")
|
51
|
-
end
|
41
|
+
gem(name, *ver) if ver
|
42
|
+
require name
|
43
|
+
Merb.logger.info!("loading gem '#{name}' ...")
|
52
44
|
rescue LoadError
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
else
|
57
|
-
Merb.logger.info!("loading gem '#{name}' ...")
|
58
|
-
# Failed requiring as a gem, let's try loading with a normal require.
|
59
|
-
require name
|
60
|
-
end
|
45
|
+
Merb.logger.info!("loading gem '#{name}' ...")
|
46
|
+
# Failed requiring as a gem, let's try loading with a normal require.
|
47
|
+
require name
|
61
48
|
end
|
62
49
|
end
|
63
50
|
|