Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Ruby Examine
# for console usage
# outputs columnized + justified inspection of selected attributes.
#
# examples:
#
# User.limit(2).examine(:name, :email)
# name email
# Jordan Brough jordan@example.com
# Joe Shmoe joe@example.com
# => nil
#
# User.limit(3).examine(:name, :email, {subscription_count: -> (u) { u.subscriptions.count }})
# name email subscription_count
# Jordan Brough jordan@example.com 1
# John Doe john@john.com 0
# Joe Shjoe joe@example.com 5
# => nil
# to always include this in IRB save this to ~/.irbrc.examine and add the following to your ~/.irbrc:
#
# load File.expand_path('../.irbrc.examine', __FILE__)
#
module JordanBrough
module Examine
module InstanceMethods
def examine(*attrs)
JordanBrough::Examine.examine(self, *attrs)
end
end
module_function
# for console usage
# outputs columnized + justified inspection of selected attributes.
# see Object#pluck for valid attrs
#
# examples:
#
# User.all.random(2).examine(:name, :email)
# name email
# Jordan Brough jordan+a4c@animoto.com
# Jordan Brough jordan+sep30_2@animoto.com
# => nil
#
# User.all.random(5).examine(:name, :email, [:subscription_count, proc {|u| u.subscriptions.count}])
# name email subscription_count
# Jordan Brough jordan+oct21@animoto.com 1
# John Doe john@john.com 0
# Tom Clifton tom@animoto.com 0
# Jordan Brough jordan+a4c@animoto.com 2
# Jordan Brough jordan+b2b@animoto.com 0
# => nil
def examine(object, *attrs, &block)
require 'date'
array = object.respond_to?(:to_ary) ? object.to_ary : [object]
printer = block || lambda do |keys, hashes, val_to_s|
max_widths = {}
keys.each do |key|
max_widths[key] = ([key.to_s.size] + hashes.map { |hash| val_to_s.call(hash[key]).size }).max
end
keys_str = keys.map { |key| key.to_s.ljust(max_widths[key]) }.join(' ') + "\n"
keys_str + hashes.map do |hash|
hash.map { |key, val| val_to_s.call(val).ljust(max_widths[key]) }.join(' ')
end.join("\n")
end
val_to_s = lambda do |val|
case val
when Time, DateTime then val.strftime('%Y-%m-%d %H:%M:%S')
when Date then val.strftime('%Y-%m-%d')
else val.to_s
end
end
keys = attrs.map { |attr| attr.is_a?(Hash) ? attr.keys.first : attr }
hashes = array.map { |item| pluck(item, attrs) } # note: pluck returns an ActiveSupport::OrderedHash
printer.call(keys, hashes, val_to_s)
end
def examine_csv(object, *attrs)
require 'csv'
examine(object, *attrs) do |keys, hashes, val_to_s|
keys.to_csv + hashes.map do |hash|
hash.map { |key, val| val_to_s.call(val) }.to_csv
end.join
end
end
def pluck(object, attrs)
key_vals = attrs.map do |item|
key = item.is_a?(Hash) ? item.keys.first : item
val = item.is_a?(Hash) ? item.values.first : item
val = if val.respond_to?(:call)
if val.respond_to?(:arity) && val.arity.abs > 0
val.call(object)
else
val.call
end
else
object.instance_eval(val.to_s)
end
[key, val]
end
Hash[key_vals]
end
end
end
Object.send(:include, JordanBrough::Examine::InstanceMethods) # using "send" for Ruby < 2.1 compatibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment