Load useful data in the rails console

The basics

I spend plenty of time in the rails console in my local dev environment, and I often find myself in need of dummy data or specific objects set up to mess around with. For example, the user I test most things with is KevinKuchta, so I might run kevin = User.find_by_username('KevinKuchta') . It's like 40 characters long, but I type it often enough that I'd love to optimize it (and similar bits of code).

It's pretty simple:

Make sure you're using pry. It's better than irb, and also lets us have per-project rc files (irb only has the global ~/.irbrc ). Use pry-rails . It's possible to configure rails to use pry for rails console sessions, but pry-rails does it for you. Make yourself a .pryrc file at the root of your project. These bits of code I want are, at least for me, all project-specific. I don't want to try to load the KevinKuchta user over in an unrelated project that doesn't even have a user model, so I need a project-specific pryrc. Fill it up with this: class Object private def kevin User.find_by_username('KevinKuchta') end end Save the .pryrc file and open the rails console. Enter kevin , and the above code will be called. ~/code/some_rails_project> bundle exec rails c Loading development environment (Rails 3.2.17) [1] pry(main)> kevin User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."username" = 'KevinKuchta' LIMIT 1 => #<User id: 123, username: "KevinKuchta">

As you can see, we're tacking my helper function onto the global object. We could make a Util class or something, but I'd rather call kevin than Util.kevin . The functions on Object are accessible without any prefix, allowing us to call our methods more succinctly

Note that we declare out helper function as private so it's not available on anything that extends ruby's base object: Hash.new.kevin would return my user if it weren't private.

A bit better

Now, this still isn't quite as nice as I'd like it. kevin is reloaded from the database every time I use it, wiping out any unsave changes. Let's memoize it:

def kevin @_kevin ||= User.find_by_username('KevinKuchta') end

Now I can modify that record and the database is only hit once:

[1] pry(main)> kevin.email = 'foo' User Load (0.8ms) SELECT "users".* FROM "users" WHERE ... => "foo" [2] pry(main)> kevin.email => "foo"

A just a little further

Now let's generalize that logic a bit so we can easily define as many of these variables as we want. It's a bit of ugly metaprogramming, but this isn't production code, so it's alright!

class Object private def populate(name, &block) self.class.send(:define_method, name) do instance_variable_name = '@_' + name value = instance_variable_get(instance_variable_name) unless value value = block.call instance_variable_set(instance_variable_name, value) end value end end end populate('kevin') do User.find_by_username('KevinKuchta') end

Now there's a nice little method you can use. These variable can even depend on eachother:

populate('balance') do kevin.account.balance end

And there you have it. Lazy-loaded, prepopulated data in your rails console.