actionpack 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (40) hide show
  1. data/CHANGELOG +78 -0
  2. data/README +1 -1
  3. data/install.rb +4 -2
  4. data/lib/action_controller.rb +3 -0
  5. data/lib/action_controller/base.rb +16 -8
  6. data/lib/action_controller/caching.rb +401 -0
  7. data/lib/action_controller/cgi_process.rb +2 -1
  8. data/lib/action_controller/cookies.rb +3 -3
  9. data/lib/action_controller/filters.rb +94 -24
  10. data/lib/action_controller/layout.rb +63 -21
  11. data/lib/action_controller/session/mem_cache_store.rb +1 -1
  12. data/lib/action_controller/support/binding_of_caller.rb +72 -68
  13. data/lib/action_controller/support/breakpoint.rb +526 -524
  14. data/lib/action_controller/support/class_inheritable_attributes.rb +105 -29
  15. data/lib/action_controller/support/core_ext.rb +1 -0
  16. data/lib/action_controller/support/core_ext/hash.rb +5 -0
  17. data/lib/action_controller/support/core_ext/hash/keys.rb +35 -0
  18. data/lib/action_controller/support/core_ext/numeric.rb +7 -0
  19. data/lib/action_controller/support/core_ext/numeric/bytes.rb +33 -0
  20. data/lib/action_controller/support/core_ext/numeric/time.rb +59 -0
  21. data/lib/action_controller/support/core_ext/string.rb +5 -0
  22. data/lib/action_controller/support/core_ext/string/inflections.rb +41 -0
  23. data/lib/action_controller/support/dependencies.rb +1 -14
  24. data/lib/action_controller/support/inflector.rb +6 -6
  25. data/lib/action_controller/support/misc.rb +0 -24
  26. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +7 -4
  27. data/lib/action_controller/test_process.rb +9 -0
  28. data/lib/action_controller/url_rewriter.rb +13 -5
  29. data/lib/action_view/helpers/active_record_helper.rb +10 -3
  30. data/lib/action_view/helpers/cache_helper.rb +10 -0
  31. data/lib/action_view/helpers/form_helper.rb +25 -2
  32. data/lib/action_view/helpers/form_options_helper.rb +1 -2
  33. data/lib/action_view/helpers/url_helper.rb +8 -5
  34. data/lib/action_view/partials.rb +2 -2
  35. data/rakefile +6 -3
  36. data/test/controller/filters_test.rb +118 -3
  37. data/test/controller/render_test.rb +5 -0
  38. data/test/controller/send_file_test.rb +24 -0
  39. data/test/controller/url_test.rb +47 -2
  40. metadata +16 -2
@@ -2,6 +2,7 @@ require 'action_controller/cgi_ext/cgi_ext'
2
2
  require 'action_controller/cgi_ext/cookie_performance_fix'
3
3
  require 'action_controller/session/drb_store'
4
4
  require 'action_controller/session/active_record_store'
5
+ require 'action_controller/session/mem_cache_store'
5
6
 
6
7
  module ActionController #:nodoc:
7
8
  class Base
@@ -61,7 +62,7 @@ module ActionController #:nodoc:
61
62
  end
62
63
 
63
64
  def host
64
- env["HTTP_X_FORWARDED_HOST"] || @cgi.host.split(":").first
65
+ env["HTTP_X_FORWARDED_HOST"] || @cgi.host.to_s.split(":").first
65
66
  end
66
67
 
67
68
  def session
@@ -51,16 +51,16 @@ module ActionController #:nodoc:
51
51
  options = { "name" => name, "value" => options }
52
52
  end
53
53
 
54
- set_cookie(name, options)
54
+ set_cookie(options)
55
55
  end
56
56
 
57
57
  # Removes the cookie on the client machine by setting the value to an empty string.
58
58
  def delete(name)
59
- set_cookie(name, "name" => name, "value" => "")
59
+ set_cookie("name" => name.to_s, "value" => "")
60
60
  end
61
61
 
62
62
  private
63
- def set_cookie(name, options) #:doc:
63
+ def set_cookie(options) #:doc:
64
64
  options["path"] = "/" unless options["path"]
65
65
  cookie = CGI::Cookie.new(options)
66
66
  @controller.logger.info "Cookie set: #{cookie}" unless @controller.logger.nil?
@@ -3,7 +3,7 @@ module ActionController #:nodoc:
3
3
  def self.append_features(base)
4
4
  super
5
5
  base.extend(ClassMethods)
6
- base.class_eval { include ActionController::Filters::InstanceMethods }
6
+ base.send(:include, ActionController::Filters::InstanceMethods)
7
7
  end
8
8
 
9
9
  # Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do
@@ -126,19 +126,47 @@ module ActionController #:nodoc:
126
126
  # report_result
127
127
  # end
128
128
  # end
129
+ #
130
+ # == Filter conditions
131
+ #
132
+ # Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to
133
+ # exclude or the actions to include when executing the filter. Available conditions are +:only+ or +:except+, both
134
+ # of which accept an arbitrary number of method references. For example:
135
+ #
136
+ # class Journal < ActionController::Base
137
+ # # only require authentication if the current action is edit or delete
138
+ # before_filter :authorize, :only => [ :edit, :delete ]
139
+ #
140
+ # private
141
+ # def authorize
142
+ # # redirect to login unless authenticated
143
+ # end
144
+ # end
145
+ #
146
+ # When setting conditions on inline method (proc) filters the condition must come first and be placed in parenthesis.
147
+ #
148
+ # class UserPreferences < ActionController::Base
149
+ # before_filter(:except => :new) { # some proc ... }
150
+ # # ...
151
+ # end
152
+ #
129
153
  module ClassMethods
130
154
  # The passed <tt>filters</tt> will be appended to the array of filters that's run _before_ actions
131
155
  # on this controller are performed.
132
156
  def append_before_filter(*filters, &block)
133
- filters << block if block_given?
134
- append_filter_to_chain("before", filters)
157
+ conditions = extract_conditions!(filters)
158
+ filters << block if block_given?
159
+ add_action_conditions(filters, conditions)
160
+ append_filter_to_chain("before", filters)
135
161
  end
136
162
 
137
163
  # The passed <tt>filters</tt> will be prepended to the array of filters that's run _before_ actions
138
164
  # on this controller are performed.
139
165
  def prepend_before_filter(*filters, &block)
140
- filters << block if block_given?
141
- prepend_filter_to_chain("before", filters)
166
+ conditions = extract_conditions!(filters)
167
+ filters << block if block_given?
168
+ add_action_conditions(filters, conditions)
169
+ prepend_filter_to_chain("before", filters)
142
170
  end
143
171
 
144
172
  # Short-hand for append_before_filter since that's the most common of the two.
@@ -147,15 +175,19 @@ module ActionController #:nodoc:
147
175
  # The passed <tt>filters</tt> will be appended to the array of filters that's run _after_ actions
148
176
  # on this controller are performed.
149
177
  def append_after_filter(*filters, &block)
150
- filters << block if block_given?
151
- append_filter_to_chain("after", filters)
178
+ conditions = extract_conditions!(filters)
179
+ filters << block if block_given?
180
+ add_action_conditions(filters, conditions)
181
+ append_filter_to_chain("after", filters)
152
182
  end
153
183
 
154
184
  # The passed <tt>filters</tt> will be prepended to the array of filters that's run _after_ actions
155
185
  # on this controller are performed.
156
186
  def prepend_after_filter(*filters, &block)
157
- filters << block if block_given?
158
- prepend_filter_to_chain("after", filters)
187
+ conditions = extract_conditions!(filters)
188
+ filters << block if block_given?
189
+ add_action_conditions(filters, conditions)
190
+ prepend_filter_to_chain("after", filters)
159
191
  end
160
192
 
161
193
  # Short-hand for append_after_filter since that's the most common of the two.
@@ -169,8 +201,8 @@ module ActionController #:nodoc:
169
201
  # A#before
170
202
  # A#after
171
203
  # B#after
172
- def append_around_filter(filters)
173
- for filter in [filters].flatten
204
+ def append_around_filter(*filters)
205
+ for filter in filters.flatten
174
206
  ensure_filter_responds_to_before_and_after(filter)
175
207
  append_before_filter { |c| filter.before(c) }
176
208
  prepend_after_filter { |c| filter.after(c) }
@@ -185,8 +217,8 @@ module ActionController #:nodoc:
185
217
  # B#before
186
218
  # B#after
187
219
  # A#after
188
- def prepend_around_filter(filters)
189
- for filter in [filters].flatten
220
+ def prepend_around_filter(*filters)
221
+ for filter in filters.flatten
190
222
  ensure_filter_responds_to_before_and_after(filter)
191
223
  prepend_before_filter { |c| filter.before(c) }
192
224
  append_after_filter { |c| filter.after(c) }
@@ -206,6 +238,16 @@ module ActionController #:nodoc:
206
238
  read_inheritable_attribute("after_filters")
207
239
  end
208
240
 
241
+ # Returns a mapping between filters and the actions that may run them.
242
+ def included_actions #:nodoc:
243
+ read_inheritable_attribute("included_actions") || {}
244
+ end
245
+
246
+ # Returns a mapping between filters and actions that may not run them.
247
+ def excluded_actions #:nodoc:
248
+ read_inheritable_attribute("excluded_actions") || {}
249
+ end
250
+
209
251
  private
210
252
  def append_filter_to_chain(condition, filters)
211
253
  write_inheritable_array("#{condition}_filters", filters)
@@ -220,6 +262,22 @@ module ActionController #:nodoc:
220
262
  raise ActionControllerError, "Filter object must respond to both before and after"
221
263
  end
222
264
  end
265
+
266
+ def extract_conditions!(filters)
267
+ return nil unless filters.last.is_a? Hash
268
+ filters.pop
269
+ end
270
+
271
+ def add_action_conditions(filters, conditions)
272
+ return unless conditions
273
+ included, excluded = conditions[:only], conditions[:except]
274
+ write_inheritable_hash("included_actions", condition_hash(filters, included)) && return if included
275
+ write_inheritable_hash("excluded_actions", condition_hash(filters, excluded)) if excluded
276
+ end
277
+
278
+ def condition_hash(filters, *actions)
279
+ filters.inject({}) {|hash, filter| hash.merge(filter => actions.flatten.map {|action| action.to_s})}
280
+ end
223
281
  end
224
282
 
225
283
  module InstanceMethods # :nodoc:
@@ -252,18 +310,21 @@ module ActionController #:nodoc:
252
310
  private
253
311
  def call_filters(filters)
254
312
  filters.each do |filter|
255
- if Symbol === filter
256
- if self.send(filter) == false then return false end
257
- elsif filter_block?(filter)
258
- if filter.call(self) == false then return false end
259
- elsif filter_class?(filter)
260
- if filter.filter(self) == false then return false end
261
- else
262
- raise(
263
- ActionControllerError,
264
- "Filters need to be either a symbol, proc/method, or class implementing a static filter method"
265
- )
313
+ next if action_exempted?(filter)
314
+ filter_result = case
315
+ when filter.is_a?(Symbol)
316
+ self.send(filter)
317
+ when filter_block?(filter)
318
+ filter.call(self)
319
+ when filter_class?(filter)
320
+ filter.filter(self)
321
+ else
322
+ raise(
323
+ ActionControllerError,
324
+ "Filters need to be either a symbol, proc/method, or class implementing a static filter method"
325
+ )
266
326
  end
327
+ return false if filter_result == false
267
328
  end
268
329
  end
269
330
 
@@ -274,6 +335,15 @@ module ActionController #:nodoc:
274
335
  def filter_class?(filter)
275
336
  filter.respond_to?("filter")
276
337
  end
338
+
339
+ def action_exempted?(filter)
340
+ case
341
+ when self.class.included_actions[filter]
342
+ !self.class.included_actions[filter].include?(action_name)
343
+ when self.class.excluded_actions[filter]
344
+ self.class.excluded_actions[filter].include?(action_name)
345
+ end
346
+ end
277
347
  end
278
348
  end
279
349
  end
@@ -58,12 +58,21 @@ module ActionController #:nodoc:
58
58
  # <h1>Welcome</h1>
59
59
  # Off-world colonies offers you a chance to start a new life
60
60
  #
61
+ # == Automatic layout assignment
62
+ #
63
+ # If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically
64
+ # set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named
65
+ # <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as
66
+ # the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt>
67
+ # and this will be set as the default controller if there is no layout with the same name as the current controller and there is
68
+ # no layout explicitly assigned with the +layout+ method. Setting a layout explicity will always override the automatic behaviour.
69
+ #
61
70
  # == Inheritance for layouts
62
71
  #
63
72
  # Layouts are shared downwards in the inheritance hierarchy, but not upwards. Examples:
64
73
  #
65
74
  # class BankController < ActionController::Base
66
- # layout "layouts/bank_standard"
75
+ # layout "bank_standard"
67
76
  #
68
77
  # class InformationController < BankController
69
78
  #
@@ -73,7 +82,7 @@ module ActionController #:nodoc:
73
82
  # class EmployeeController < BankController
74
83
  # layout nil
75
84
  #
76
- # The InformationController uses "layouts/bank_standard" inherited from the BankController, the VaultController overwrites
85
+ # The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites
77
86
  # and picks the layout dynamically, and the EmployeeController doesn't want to use a layout at all.
78
87
  #
79
88
  # == Types of layouts
@@ -104,16 +113,31 @@ module ActionController #:nodoc:
104
113
  # class WeblogController < ActionController::Base
105
114
  # layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" }
106
115
  #
107
- # Of course, the most common way of specifying a layout is still just as a plain template path:
116
+ # Of course, the most common way of specifying a layout is still just as a plain template name:
108
117
  #
109
118
  # class WeblogController < ActionController::Base
110
- # layout "layouts/weblog_standard"
119
+ # layout "weblog_standard"
111
120
  #
112
- # == Avoiding the use of a layout
121
+ # If no directory is specified for the template name, the template will by default by looked for in +app/views/layouts/+.
113
122
  #
114
- # If you have a layout that by default is applied to all the actions of a controller, you still have the option to rendering
115
- # a given action without a layout. Just use the method <tt>render_without_layout</tt>, which works just like Base.render --
116
- # it just doesn't apply any layouts.
123
+ # == Conditional layouts
124
+ #
125
+ # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering
126
+ # a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The
127
+ # +:only+ and +:except+ options can be passed to the layout call. For example:
128
+ #
129
+ # class WeblogController < ActionController::Base
130
+ # layout "weblog_standard", :except => :rss
131
+ #
132
+ # # ...
133
+ #
134
+ # end
135
+ #
136
+ # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout
137
+ # around the rendered view.
138
+ #
139
+ # Both the +:only+ and +:except+ condition can accept an aribtrary number of method references, so +:except => [ :rss, :text_only ]+
140
+ # is valid, as is # +:except => :rss+.
117
141
  #
118
142
  # == Using a different layout in the action render call
119
143
  #
@@ -130,32 +154,36 @@ module ActionController #:nodoc:
130
154
  #
131
155
  # As you can see, you pass the template as the first parameter, the status code as the second ("200" is OK), and the layout
132
156
  # as the third.
133
- #
134
- # == Automatic layout assignment
135
- #
136
- # If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically
137
- # set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named
138
- # <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as
139
- # the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt>
140
- # and this will be set as the default controller if there is no layout with the same name as the current controller and there is
141
- # no layout explicitly assigned with the +layout+ method. Setting a layout explicity will always override the automatic behaviour.
142
157
  module ClassMethods
143
158
  # If a layout is specified, all actions rendered through render and render_action will have their result assigned
144
159
  # to <tt>@content_for_layout</tt>, which can then be used by the layout to insert their contents with
145
160
  # <tt><%= @content_for_layout %></tt>. This layout can itself depend on instance variables assigned during action
146
161
  # performance and have access to them as any normal template would.
147
- def layout(template_name)
162
+ def layout(template_name, conditions = {})
163
+ add_layout_conditions(conditions)
148
164
  write_inheritable_attribute "layout", template_name
149
165
  end
150
166
 
167
+ def layout_conditions #:nodoc:
168
+ read_inheritable_attribute("layout_conditions")
169
+ end
170
+
151
171
  private
152
172
  def inherited(child)
153
173
  inherited_without_layout(child)
154
- child.layout(child.controller_name) unless layout_list.grep(/^#{child.controller_name}\.r(?:xml|html)$/).empty?
174
+ child.layout(child.controller_name) unless layout_list.grep(/^#{child.controller_name}\.r(?:x|ht)ml$/).empty?
155
175
  end
156
176
 
157
177
  def layout_list
158
- Dir.glob("#{template_root}/layouts/*.r{xml,html}").map { |layout| File.basename(layout) }
178
+ Dir.glob("#{template_root}/layouts/*.r{x,ht}ml").map { |layout| File.basename(layout) }
179
+ end
180
+
181
+ def add_layout_conditions(conditions)
182
+ write_inheritable_hash "layout_conditions", normalize_conditions(conditions)
183
+ end
184
+
185
+ def normalize_conditions(conditions)
186
+ conditions.inject({}) {|hash, (key, value)| hash.merge(key => [value].flatten.map {|action| action.to_s})}
159
187
  end
160
188
  end
161
189
 
@@ -174,7 +202,7 @@ module ActionController #:nodoc:
174
202
  end
175
203
 
176
204
  def render_with_layout(template_name = default_template_name, status = nil, layout = nil) #:nodoc:
177
- if layout ||= active_layout
205
+ if layout ||= active_layout and action_has_layout?
178
206
  add_variables_to_assigns
179
207
  logger.info("Rendering #{template_name} within #{layout}") unless logger.nil?
180
208
  @content_for_layout = @template.render_file(template_name, true)
@@ -184,5 +212,19 @@ module ActionController #:nodoc:
184
212
  end
185
213
  end
186
214
 
215
+ private
216
+
217
+ def action_has_layout?
218
+ conditions = self.class.layout_conditions
219
+ case
220
+ when conditions[:only]
221
+ conditions[:only].include?(action_name)
222
+ when conditions[:except]
223
+ !conditions[:except].include?(action_name)
224
+ else
225
+ true
226
+ end
227
+ end
228
+
187
229
  end
188
230
  end
@@ -46,7 +46,7 @@ begin
46
46
  unless check_id(id)
47
47
  raise ArgumentError, "session_id '%s' is invalid" % id
48
48
  end
49
- @cache = options['cache']
49
+ @cache = options['cache'] || MemCache.new('localhost')
50
50
  @session_key = "session:#{id}"
51
51
  @hash = {}
52
52
  end
@@ -1,81 +1,85 @@
1
1
  begin
2
2
  require 'simplecc'
3
3
  rescue LoadError
4
- def Continuation.create(*args, &block)
5
- cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
6
- result ||= args
7
- return *[cc, *result]
4
+ class Continuation #:nodoc:
5
+ def create(*args, &block)
6
+ cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
7
+ result ||= args
8
+ return *[cc, *result]
9
+ end
8
10
  end
9
11
  end
10
12
 
11
- # This method returns the binding of the method that called your
12
- # method. It will raise an Exception when you're not inside a method.
13
- #
14
- # It's used like this:
15
- # def inc_counter(amount = 1)
16
- # Binding.of_caller do |binding|
17
- # # Create a lambda that will increase the variable 'counter'
18
- # # in the caller of this method when called.
19
- # inc = eval("lambda { |arg| counter += arg }", binding)
20
- # # We can refer to amount from inside this block safely.
21
- # inc.call(amount)
22
- # end
23
- # # No other statements can go here. Put them inside the block.
24
- # end
25
- # counter = 0
26
- # 2.times { inc_counter }
27
- # counter # => 2
28
- #
29
- # Binding.of_caller must be the last statement in the method.
30
- # This means that you will have to put everything you want to
31
- # do after the call to Binding.of_caller into the block of it.
32
- # This should be no problem however, because Ruby has closures.
33
- # If you don't do this an Exception will be raised. Because of
34
- # the way that Binding.of_caller is implemented it has to be
35
- # done this way.
36
- def Binding.of_caller(&block)
37
- old_critical = Thread.critical
38
- Thread.critical = true
39
- count = 0
40
- cc, result, error, extra_data = Continuation.create(nil, nil)
41
- error.call if error
13
+ class Binding #:nodoc:
14
+ # This method returns the binding of the method that called your
15
+ # method. It will raise an Exception when you're not inside a method.
16
+ #
17
+ # It's used like this:
18
+ # def inc_counter(amount = 1)
19
+ # Binding.of_caller do |binding|
20
+ # # Create a lambda that will increase the variable 'counter'
21
+ # # in the caller of this method when called.
22
+ # inc = eval("lambda { |arg| counter += arg }", binding)
23
+ # # We can refer to amount from inside this block safely.
24
+ # inc.call(amount)
25
+ # end
26
+ # # No other statements can go here. Put them inside the block.
27
+ # end
28
+ # counter = 0
29
+ # 2.times { inc_counter }
30
+ # counter # => 2
31
+ #
32
+ # Binding.of_caller must be the last statement in the method.
33
+ # This means that you will have to put everything you want to
34
+ # do after the call to Binding.of_caller into the block of it.
35
+ # This should be no problem however, because Ruby has closures.
36
+ # If you don't do this an Exception will be raised. Because of
37
+ # the way that Binding.of_caller is implemented it has to be
38
+ # done this way.
39
+ def of_caller(&block)
40
+ old_critical = Thread.critical
41
+ Thread.critical = true
42
+ count = 0
43
+ cc, result, error, extra_data = Continuation.create(nil, nil)
44
+ error.call if error
42
45
 
43
- tracer = lambda do |*args|
44
- type, context, extra_data = args[0], args[4], args
45
- if type == "return"
46
- count += 1
47
- # First this method and then calling one will return --
48
- # the trace event of the second event gets the context
49
- # of the method which called the method that called this
50
- # method.
51
- if count == 2
52
- # It would be nice if we could restore the trace_func
53
- # that was set before we swapped in our own one, but
54
- # this is impossible without overloading set_trace_func
55
- # in current Ruby.
46
+ tracer = lambda do |*args|
47
+ type, context, extra_data = args[0], args[4], args
48
+ if type == "return"
49
+ count += 1
50
+ # First this method and then calling one will return --
51
+ # the trace event of the second event gets the context
52
+ # of the method which called the method that called this
53
+ # method.
54
+ if count == 2
55
+ # It would be nice if we could restore the trace_func
56
+ # that was set before we swapped in our own one, but
57
+ # this is impossible without overloading set_trace_func
58
+ # in current Ruby.
59
+ set_trace_func(nil)
60
+ cc.call(eval("binding", context), nil, extra_data)
61
+ end
62
+ elsif type == "line" then
63
+ nil
64
+ elsif type == "c-return" and extra_data[3] == :set_trace_func then
65
+ nil
66
+ else
56
67
  set_trace_func(nil)
57
- cc.call(eval("binding", context), nil, extra_data)
68
+ error_msg = "Binding.of_caller used in non-method context or " +
69
+ "trailing statements of method using it aren't in the block."
70
+ cc.call(nil, lambda { raise(ArgumentError, error_msg) }, nil)
58
71
  end
59
- elsif type == "line" then
60
- nil
61
- elsif type == "c-return" and extra_data[3] == :set_trace_func then
62
- nil
63
- else
64
- set_trace_func(nil)
65
- error_msg = "Binding.of_caller used in non-method context or " +
66
- "trailing statements of method using it aren't in the block."
67
- cc.call(nil, lambda { raise(ArgumentError, error_msg) }, nil)
68
72
  end
69
- end
70
73
 
71
- unless result
72
- set_trace_func(tracer)
73
- return nil
74
- else
75
- Thread.critical = old_critical
76
- case block.arity
77
- when 1 then yield(result)
78
- else yield(result, extra_data)
74
+ unless result
75
+ set_trace_func(tracer)
76
+ return nil
77
+ else
78
+ Thread.critical = old_critical
79
+ case block.arity
80
+ when 1 then yield(result)
81
+ else yield(result, extra_data)
82
+ end
79
83
  end
80
84
  end
81
- end
85
+ end