banister / method_source

return the sourcecode for a method
MIT License
361 stars 43 forks source link

EOF error when using source on methods defined via class/instance eval #13

Open redgetan opened 12 years ago

redgetan commented 12 years ago
[40] pry(main)> ActiveRecord::Base.method(:before_save).source
EOFError: end of file reached
from /Users/reg/.rvm/gems/ruby-1.9.3-p125@pry_sbox/gems/method_source-0.7.1/lib/method_source.rb:44:in `readline'

/Users/reg/.rvm/gems/ruby-1.9.3-p125@pry_sbox/gems/activemodel-3.2.3/lib/active_model/callbacks.rb: 109

    def _define_before_model_callback(klass, callback) #:nodoc:
      klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
        def self.before_#{callback}(*args, &block)
          set_callback(:#{callback}, :before, *args, &block)
        end
      CALLBACK
    end

As you can see below, the # symbol will be interpreted as a comment so valid_expression? would never return true and readline just keeps going

       def self.before_#{callback}(*args, &block)
          set_callback(:#{callback}, :before, *args, &block)
        end

Problem would have been solved if syntax checking is done at the start of klass.class_eval line instead of def self.before_ as suggested by @banister.

redgetan commented 12 years ago

it's tricky to find which line the class_eval is called though because if you just search for the regex /class_eval|module_eval/, then it will capture even comment lines that just include those words.

ie. if the before_save code is modified to the one below, then its gonna potentially create problems

    def _define_before_model_callback(klass, callback) #:nodoc:
      klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
        # 
        # this is a class_eval HACK, might change in the future API release
        #
        def self.before_#{callback}(*args, &block)
          set_callback(:#{callback}, :before, *args, &block)
        end
      CALLBACK
    end