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:
pry-rails. It's possible to configure rails to use pry for rails console sessions, but pry-rails does it for you.
.pryrcfile 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
.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)  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
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.
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:
 pry(main)> kevin.email = 'foo' User Load (0.8ms) SELECT "users".* FROM "users" WHERE ... => "foo"  pry(main)> kevin.email => "foo"
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.