Module: NinjaDecorators::ClassMethods
- Defined in:
- lib/ninja_decorators.rb
Instance Method Summary collapse
- #after_filter(after_method, method_names) ⇒ Object
- #around_filter(around_method, method_names) ⇒ Object
- #before_filter(before_method, method_names) ⇒ Object
- #delayed_alias_method_chains ⇒ Object
- #filter_factory(filter_method, method_names, filter_type) ⇒ Object
- #method_added(meth) ⇒ Object
-
#ninja_method_chain(target, feature) ⇒ Object
This was largely lifted from ActiveSupport’s alias_method_chain.
Instance Method Details
#after_filter(after_method, method_names) ⇒ Object
33 34 35 |
# File 'lib/ninja_decorators.rb', line 33 def after_filter(after_method, method_names) filter_factory(after_method, method_names, :after) end |
#around_filter(around_method, method_names) ⇒ Object
25 26 27 |
# File 'lib/ninja_decorators.rb', line 25 def around_filter(around_method, method_names) filter_factory(around_method, method_names, :around) end |
#before_filter(before_method, method_names) ⇒ Object
29 30 31 |
# File 'lib/ninja_decorators.rb', line 29 def before_filter(before_method, method_names) filter_factory(before_method, method_names, :before) end |
#delayed_alias_method_chains ⇒ Object
10 11 12 |
# File 'lib/ninja_decorators.rb', line 10 def delayed_alias_method_chains @delayed_alias_method_chains ||= {} end |
#filter_factory(filter_method, method_names, filter_type) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ninja_decorators.rb', line 37 def filter_factory(filter_method, method_names, filter_type) method_names.each do |meth| # Build up a proc that will construct the filtered method. Execution of the proc is delayed # until we encounter the alias_method_chain call. filtered_method_builder = Proc.new do # Get a reference to the unfiltered method or, more accurately, the original method with # all previous filters already applied. This new filtered method builds up on the filters # already applied. unfiltered_method = instance_method "#{meth}_without_#{filter_type.to_s}_filter_wrapper" # Define the newly filtered method. case filter_type when :before define_method("#{meth}_with_before_filter_wrapper") do |*args| send(filter_method, *args) unfiltered_method.bind(self).call(*args) end when :around define_method("#{meth}_with_around_filter_wrapper") do |*args| send(filter_method, *args) do |*ar_args| unfiltered_method.bind(self).call(*ar_args) end end when :after define_method("#{meth}_with_after_filter_wrapper") do |*args| unfiltered_method.bind(self).call(*args) send(filter_method, *args) end end end # If the method to filter has been defined already. if self.instance_methods.include?(meth.to_s) # Filter the method with before_method. ninja_method_chain meth, "#{filter_type.to_s}_filter_wrapper", &filtered_method_builder # If the method to filter has not been defined already, delay wrapping until it has. else delayed_alias_method_chains[meth.to_s] ||= [] delayed_alias_method_chains[meth.to_s] << {"#{filter_type.to_s}_filter_wrapper" => filtered_method_builder} end end end |
#method_added(meth) ⇒ Object
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/ninja_decorators.rb', line 14 def method_added(meth) if delayed_alias_method_chains[meth.to_s] chains_arr = delayed_alias_method_chains.delete(meth.to_s) chains_arr.each do |chain| chain.each_pair do |filter_type, filtered_method_builder| ninja_method_chain meth, filter_type, &filtered_method_builder end end end end |
#ninja_method_chain(target, feature) ⇒ Object
This was largely lifted from ActiveSupport’s alias_method_chain. We needed to be able to yield to a block that could construct the with_* methods while having access to the aliased without_* methods.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/ninja_decorators.rb', line 87 def ninja_method_chain(target, feature) # Strip out punctuation on predicates or bang methods since # e.g. target?_without_feature is not a valid method name. aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1 with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}" alias_method without_method, target yield if block_given? alias_method target, with_method case when public_method_defined?(without_method) public target when protected_method_defined?(without_method) protected target when private_method_defined?(without_method) private target end end |