Ruby Object Inspection - What I Really Want is Attributes
Want to do some detective work regarding a thorny issue in your app? Ok lets use the handy inspect feature:
:001 > User.last.inspect
=> "#<User id: 32, email: \"someemail@domain.com\",
encrypted_password: \"xxx\", job_function_id: nil,
reset_password_token: nil, reset_password_sent_at: nil,
remember_created_at: nil, sign_in_count: 0,
current_sign_in_at: nil,
last_sign_in_at: \"2016-12-23 16:00:35\",
current_sign_in_ip: nil, last_sign_in_ip: \"127.0.0.1\",
confirmation_token: nil,
confirmed_at: \"2016-12-23 16:00:34\",
confirmation_sent_at: nil, unconfirmed_email: nil,
first_name: \"Some\", last_name: \"Email\",
title: nil, company_id: 4373,
phone: \"0000000000\",
account_confirmation_link: nil,
password_reset_link: nil,
account_confirmation_link_date: nil,
password_reset_link_date: nil,
active: true, inactive_date: nil,
created_at: \"2016-12-23 16:00:34\",
updated_at: \"2016-12-23 16:42:18\", failed_attempts: 0,
unlock_token: nil, locked_at: nil>"
That is useful. I guess. What if we took out some of the #Object stuff by just looking at attributes
:002 > User.last.attributes
=> {"id"=>32, "email"=>\"someemail@domain.com\",
"encrypted_password"=>"xxx", "job_function_id"=>nil,
"reset_password_token"=>nil,
"reset_password_sent_at"=>nil,
"remember_created_at"=>nil,
"sign_in_count"=>0, "current_sign_in_at"=>nil,
"last_sign_in_at"=>Fri, 23 Dec 2016 16:00:35 UTC +00:00,
"current_sign_in_ip"=>nil, "last_sign_in_ip"=>"127.0.0.1",
"confirmation_token"=>nil,
"confirmed_at"=>Fri, 23 Dec 2016 16:00:34 UTC +00:00,
"confirmation_sent_at"=>nil,
"unconfirmed_email"=>nil, "first_name"=>"Some",
"last_name"=>"Email", "title"=>nil,
"company_id"=>4373, "phone"=>"0000000000",
"account_confirmation_link"=>nil,
"password_reset_link"=>nil,
"account_confirmation_link_date"=>nil,
"password_reset_link_date"=>nil,
"active"=>true, "inactive_date"=>nil,
"created_at"=>Fri, 23 Dec 2016 16:00:34 UTC +00:00,
"updated_at"=>Fri, 23 Dec 2016 16:42:18 UTC +00:00,
"failed_attempts"=>0, "unlock_token"=>nil,
"locked_at"=>nil}
Hmm. Not much better. How about I convert the attributes to JSON and then print them out:
:003 > puts JSON.pretty_generate(JSON.parse(User.last.attributes.to_json))
=> {
"id": 32,
"email": "someemail@domain.com",
"encrypted_password": "xxx",
"job_function_id": null,
"reset_password_token": null,
"reset_password_sent_at": null,
"remember_created_at": null,
"sign_in_count": 0,
"current_sign_in_at": null,
"last_sign_in_at": "2016-12-23T16:00:35.333Z",
"current_sign_in_ip": null,
"last_sign_in_ip": "127.0.0.1",
"confirmation_token": null,
"confirmed_at": "2016-12-23T16:00:34.212Z",
"confirmation_sent_at": null,
"unconfirmed_email": null,
"first_name": "Some",
"last_name": "Email",
"title": null,
"company_id": 4373,
"phone": "0000000000",
"account_confirmation_link": null,
"password_reset_link": null,
"account_confirmation_link_date": null,
"password_reset_link_date": null,
"active": true,
"inactive_date": null,
"created_at": "2016-12-23T16:00:34.380Z",
"updated_at": "2016-12-23T16:42:18.934Z",
"failed_attempts": 0,
"unlock_token": null,
"locked_at": null
}
Much improved. Gee a little sorting would be even better. Since we are dealing with a hash we need to sort into an array and then convert it back to a hash:
:004 > puts JSON.pretty_generate(JSON.parse(User.last.attributes.sort.to_h.to_json))
=> {
"account_confirmation_link": null,
"account_confirmation_link_date": null,
"active": true,
"company_id": 4373,
"confirmation_sent_at": null,
"confirmation_token": null,
"confirmed_at": "2016-12-23T16:00:34.212Z",
"created_at": "2016-12-23T16:00:34.380Z",
"current_sign_in_at": null,
"current_sign_in_ip": null,
"email": "someemail@domain.com",
"encrypted_password": "xxx",
"failed_attempts": 0,
"first_name": "Some",
"id": 16787,
"inactive_date": null,
"job_function_id": null,
"last_name": "Email",
"last_sign_in_at": "2016-12-23T16:00:35.333Z",
"last_sign_in_ip": "127.0.0.1",
"locked_at": null,
"password_reset_link": null,
"password_reset_link_date": null,
"phone": "0000000000",
"remember_created_at": null,
"reset_password_sent_at": null,
"reset_password_token": null,
"sign_in_count": 0,
"title": null,
"unconfirmed_email": null,
"unlock_token": null,
"updated_at": "2016-12-23T16:42:18.934Z"
}
Seems very useful for locating issues quickly. This would be great if we had this for a method for all hashes. Monkey Patch to the rescue. Lets call our initializer hash_extend.rb:
class Hash
# pretty print
def pretty
puts JSON.pretty_generate(JSON.parse(self.sort.to_h.to_json))
"=========== for display only ============="
end
end
Restart your console and check out the pretty method:
:001 > User.last.attributes.pretty
=> {
"account_confirmation_link": null,
"account_confirmation_link_date": null,
"active": true,
"company_id": 4373,
"confirmation_sent_at": null,
"confirmation_token": null,
"confirmed_at": "2016-12-23T16:00:34.212Z",
"created_at": "2016-12-23T16:00:34.380Z",
"current_sign_in_at": null,
"current_sign_in_ip": null,
"email": "someemail@domain.com",
"encrypted_password": "xxx",
"failed_attempts": 0,
"first_name": "Some",
"id": 16787,
"inactive_date": null,
"job_function_id": null,
"last_name": "Email",
"last_sign_in_at": "2016-12-23T16:00:35.333Z",
"last_sign_in_ip": "127.0.0.1",
"locked_at": null,
"password_reset_link": null,
"password_reset_link_date": null,
"phone": "0000000000",
"remember_created_at": null,
"reset_password_sent_at": null,
"reset_password_token": null,
"sign_in_count": 0,
"title": null,
"unconfirmed_email": null,
"unlock_token": null,
"updated_at": "2016-12-23T16:42:18.934Z"
}
=> "=========== for display only ============="
Note we tack on for display only to the output just to identify the helper status of this method, since we are extending a core class.