Updates from ThomasPowell Toggle Comment Threads | Keyboard Shortcuts

  • ThomasPowell 11:07 pm on June 14, 2022 Permalink | Reply
    Tags: alias, define_method, metaprogramming,   

    Ruby object creation and method call debugging without mangling your gems directory 

    The Problem: Debugging Calls to Code in Gems

    Say you’re having a problem that ultimately doesn’t manifest itself until you get somewhere in gem source code, and the exception or symptoms don’t clearly indicate why things are breaking. This can especially be the case with test setups that leak mocks or state between tests. You can, of course edit the gem source, but why not alias the original method and debug with a substitute method that calls the original?

    Hooking into new via an alias

    If you have some hunches about object initialization going awry between working and failing versions of a test, you can declare the following troubleshoot_new method (wherever, as long as it’s accessible in your example):

    def troubleshoot_new(klass)
      klass.class_eval do
        class << self
          alias :old_new :new
          def new(*args)
            puts self.to_s + args.inspect
            old_new *args
          end
        end
      end
    end
    

    The above code aliases the original new method on the class and inserts a logging of the class name and arguments sent to new before calling the original. This could be replaced by a hook to binding.pry or byebug to drop into a debugger instead. Then you could call troubleshoot_new(ClassName) as follows in your individual examples to track object creations.

    class Box # arbitrary class
      def initialize(x, y, z)
      end
    end
          
    troubleshoot_new(Box)
    

    Then on object instantiation you’ll get the logging (the Box[1,2,3])

    irb(main):027:0> Box.new(1,2,3)
    Box[1, 2, 3]
    => #<Box:0x00000001047c7d38>
    

    Cleaning up

    If you want to clean up after the alias

    def untroubleshoot_new(klass)
      klass.class_eval do
        class << self
          alias :new :old_new
        end
      end
    end
    
    untroubleshoot_new(Box)
    

    Which will alias the old method back:

    irb(main):029:0> Box.new(1,2,3)
    => #<Box:0x00000001047576c8>
    irb(main):030:0>
    

    Using a block to wrap the alias/unalias

    To be a little more assured that the alias/unalias will happen, this could be implemented in block form instead:

    def troubleshoot_new(klass)
      klass.class_eval do
        class << self
          alias :old_new :new
          def new(*args)
            puts self.to_s + args.inspect
            old_new *args
          end
        end
      end
    
      yield
    
      klass.class_eval do
        class << self
          alias :new :old_new
        end
      end
    end
    
    irb(main):030:1* troubleshoot_new(Box) do
    irb(main):031:1*   p Box.new(1,2,3)
    irb(main):032:0> end
    irb(main):033:0> p Box.new(4,5,6)
    Box[1, 2, 3]
    #<Box:0x0000000104886440>
    #<Box:0x00000001048860f8>
    

    Active debugging via a hook into the object creation

    Another way you can use this is to drop directly into a method deep in the call chain instead of having to debug you way into it with step in pry. I extended the new strategy to an arbitrary method (instance method shown here), since it’s often a specific method call that’s the trigger for a failure.

    def troubleshoot(klass, method)
      klass.class_eval do
        alias_method "old_#{method}".to_sym, method
        define_method method do |*args|
          puts klass.to_s + ':' + method.to_s + "->" + args.inspect
          # binding.pry # to debug from here
          send "old_#{method}".to_sym, *args
        end
      end
    
      yield
    
      klass.class_eval do
        alias_method method, "old_#{method}".to_sym
      end
    end
    
    class Box
      attr_accessor :x, :y, :z
      def initialize(x, y, z)
        @x=x
        @y=y
        @z=z
      end
    
      def join_it(insert)
        puts [x,y,z].join(insert).inspect
      end
    end
    
    troubleshoot(Box, :join_it) do
      box = Box.new(1,2,3)
      box.join_it("<->")
    end
    
    #> Box:join_it->["<->"]
    #> "1<->2<->3"
    

    The commented out binding.pry can be uncommented to jump directly into the entry point for a problem.

    May your problems rarely be this deep

    Having to dig into problems that are deep in gem source means that you’re probably already in a world of pain, but hopefully the above strategy will inspire you with additional debugging tools if the worst case debugging scenario visits you.

     
  • ThomasPowell 9:24 pm on May 28, 2022 Permalink | Reply
    Tags: index.php   

    WordPress Requiring index.php for Permalinks 

    If you are creating a new WordPress site on a server already running others and you’re not able to access permalinks that are specified without index.php in them, you may have AllowOverride off in /etc/apache2/apache2.conf

    You can specifically enable it with a Directory directive to allow overrides (in .htaccess, which is where WordPress will place them.)

    # /etc/apache/apache2.conf
    <Directory /YOUR_PATH_TO_YOUR_WORDPRESS_DIR_GOES_HERE/>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
    </Directory>
    
    # `service apache2 reload` after saving
    

     
  • ThomasPowell 12:05 am on May 28, 2022 Permalink | Reply
    Tags: visual editor,   

    WordPress Visual Editor Frustratingly not Working on New Install 

    Dude, Where’s my WordPress Visual Editor?

    I had a new install of WordPress with a manually added user, and ended up in a state in which I couldn’t enable (or disable) the WordPress visual editor or add blocks to my posts.

    Disable WordPress Visual Editor

    It turns out the manually added user that I was using was missing a nickname and the user profile changes wouldn’t save.

    Nickname is required?

    Once I added a nickname, I was able to save and toggle the Visual Editor setting and now I magically have blocks and a visual editor.

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
%d bloggers like this: