module WithResources
Constants
- VERSION
Public Class Methods
with(allocation, release_method: :close, &block)
click to toggle source
# File lib/with_resources.rb, line 10 def self.with(allocation, release_method: :close, &block) var_names = [] vars = {} allocation_block_path = nil allocation_block_lineno = nil trace = TracePoint.new(:line, :b_return) do |tp| if tp.event == :line && !tp.path.end_with?("lib/with_resources.rb") && allocation_block_path.nil? allocation_block_path = tp.path allocation_block_lineno = tp.lineno end if tp.event == :line && tp.path == allocation_block_path && tp.lineno >= allocation_block_lineno tp_binding = tp.binding tp_variables = tp_binding.local_variables if var_names.all?{|resource_var| tp_variables.include?(resource_var) } # hit! this block is resource allocation block tp_variables.each do |name| unless var_names.include?(name) var_names << name end end end end if tp.event == :b_return && tp.path == allocation_block_path && tp.lineno >= allocation_block_lineno tp_binding = tp.binding var_names.each do |name| vars[name] = tp_binding.local_variable_get(name) end end end error = nil return_value = nil begin trace.enable do allocation.call end return_value = block.call(*vars.values) rescue => e error = e error.extend(ErrorExt) ensure vars.values.reverse.each do |v| if v.respond_to?(release_method) begin v.send(release_method) rescue => e if error error.suppressed << e else error = e error.extend(ErrorExt) end end end end end raise error if error return_value end