Search code examples
ruby-on-railsruby-on-rails-4rails-consoleawesomeprint

Why doesn't Awesome Print work on some Rails collection objects?


Awesome Print generally works perfectly for me in Rails.

But when doing ap Post.all in the Rails console I only get the standard full line output.

Has it to do with the returned ActiveRecord_Relation class or something else, because when an array is returned, like in ap Post.all.each {|p| p}, Awesome Print does it's job.


Solution

  • Why not just convert it to array?

    ap Post.all.to_a
    

    or you can create a patch:

    alias :old_ap :ap
    def ap(object, option={})
      if object.class == ActiveRecord::Relation::ActiveRecord_Relation_Post
        old_ap object.to_a, option
      else
        old_ap object, option
      end
    end
    


    You are right. Maybe it's an incompatible problem with Rails4 as the last commit on github is 6 months ago. Here is the problem:

    awesome_print-1.2.0/lib/awesome_print/ext/active_record.rb@24

    def cast_with_active_record(object, type)
      cast = cast_without_active_record(object, type)
      return cast if !defined?(::ActiveRecord)
    
      if object.is_a?(::ActiveRecord::Base)
        cast = :active_record_instance
      elsif object.is_a?(Class) && object.ancestors.include?(::ActiveRecord::Base)
        cast = :active_record_class
      elsif type == :activerecord_relation #HERE the problem
        cast = :array
      end
      cast
    end
    

    the method will set the cast to array when the type is :activerecord_relation

    while in awesome_print-1.2.0/lib/awesome_print/inspector.rb@151

    def printable(object)
      case object
      when Array  then :array
      when Hash   then :hash
      when File   then :file
      when Dir    then :dir
      when Struct then :struct
      else object.class.to_s.gsub(/:+/, "_").downcase.to_sym #HERE gets the type
      end
    end
    

    But the class of Relation object in rails4 is like:

    > Post.all.class
    => ActiveRecord::Relation::ActiveRecord_Relation_Post

    So the condition in cast_with_active_record gets a type "activerecord_relation_activerecord_relation_post" rather than "activerecord_relation". Then the condition is failed, and no cast done.

    Here's a new patch that may work:

    module AwesomePrint
      class Inspector
        alias_method :old_printable, :printable
        private
        def printable(object)
          if object.class.to_s.downcase.include?("activerecord_relation")
            return :activerecord_relation
          end
          old_printable(object)
        end
      end
    end