From 6cf7a0b0e9eaaa57fba0b0cea0f3015664baa0d8 Mon Sep 17 00:00:00 2001 From: Edouard CHIN Date: Tue, 3 Jul 2018 23:15:30 -0400 Subject: Use class_eval or instance_eval when triggering lazy load hooks: - When lazy load hooks were triggered we were using `Object.instance_eval` which evaluates the block in the context of the class being passed. Most of the time that class was a `Class`. If one wants to define a instance method on the class then it wasn't possible. ```ruby class A; end; A.instance_eval do def foo puts 'bar' end end A.new.foo #> NoMethodError: undefined method `foo` A.foo #> bar ``` - This PR checks what object is passed when triggering the hooks and either call `class_eval` or `instance_eval`. My rational and assumptions being that if an instance of a class is passed, then the blocks needs to evaluate in the context of that instance (i.e. defining a method should only define it on that instance). On the other hand, if a Class or Module is passed when triggering hooks, then defining a method should define it on the class itself - #32776 Pushed me to introduce this change --- activesupport/lib/active_support/lazy_load_hooks.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'activesupport/lib/active_support/lazy_load_hooks.rb') diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb index dc8080c469..97fe8a06c1 100644 --- a/activesupport/lib/active_support/lazy_load_hooks.rb +++ b/activesupport/lib/active_support/lazy_load_hooks.rb @@ -68,7 +68,11 @@ module ActiveSupport if options[:yield] block.call(base) else - base.instance_eval(&block) + if base.is_a?(Class) || base.is_a?(Module) + base.class_eval(&block) + else + base.instance_eval(&block) + end end end end -- cgit v1.2.3