merb-core 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|