«

»

Sep
23

Inspectable accessors

Hey, it’s been a while I posted here.

So what’s the purpose ? I commonly use script/console to debug my rails applications. Today I wanted to see the values of my custom attributes model without typing model.custom_attribute. So I took a look at ActiveRecord::Base#inspect method. and the default inspect method shows me database fields. Well, let’s do some work to inspect custom attributes.
Say you have a users table with some fields : login,name,encrypted_password.

class User < ActiveRecord::Base
  attr_accessor :heroic_action
end
superman = User.find(1).inspect
superman.heroic_action = "Save the widow and the orphan"
pp superman.inspect
"#<User login: "Superman",  name: "Clark Kent",
          encrypted_password: "da39a3ee5e6b4b0d3255bfef95601890afd80709">"

Well I also want to know what heroic_action is superman doing. So i have to overwrite inspect method but I would like a DRY solution. That’s why I wrote this code :

EDIT: Just a small change to have inheritance work.

require 'active_support/core_ext/class'
 
module InspectableAttributes
 
  def self.included(base)
    base.class_inheritable_array :inspectable_attributes , :instance_writer => false
    base.extend(ClassMethods)
    base.inspectable_attributes = []
    base.class_eval do 
 
      def inspect
        inspected_values = respond_to?(:attributes_before_type_cast) ? attributes_before_type_cast.map{|k,v| "#{k.to_s}:  #{v.inspect}" } : []
        inspected_values.concat(self.class.inspectable_attributes.map { |attr| "#{attr}: #{send(attr).inspect}" })
        "#<#{self.class.name} #{inspected_values.join(', ')}>"
      end
 
    end
  end
 
  module ClassMethods
    def inspectable_attr_accessor(*args)
      attr_accessor(*args)
      self.inspectable_attributes |= args.map(&:to_s)
    end
  end
 
end
class User < ActiveRecord::Base
  include InspectableAttributes
  inspectable_attr_accessor :heroic_action
end

That’s what I was looking for !!!

superman = User.find(1).inspect
superman.heroic_action = "Save the widow and the orphan"
pp superman.inspect
"#<User login: "Superman",  name: "Clark Kent",
             encrypted_password: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
             heroic_action: "Save the widow and the orphan">"

Note that this code can be used in any ruby code requiring ‘active_support/core_ext/class’.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">