I like to use descriptive variable names, and I try to err on the side of more-descriptive if I think there's
any chance of confusion.
contract_participants
isn't terribly long, but if you're building
up all of its members from different sources (i.e., you can't really loop over it), it can get cumbersome
to type
and worse, to read. Moreover, it's different from just "participants" and they certainly
aren't "contracts," so shortening it in this case wasn't going to happen.
contract_participant.first_name = "Joe"
contract_participant.last_name = "Smith"
contract_participant.on_drugs? = params[:on_drugs?]
...
It doesn't really violate the spirit of
DRY, but it's
frustrating nevertheless.
I wanted to just have a scope for contract participants and not have to type it every time:
with(contract_participant) do
first_name = "Joe"
last_name = "Smith"
on_drugs? = params[:on_drugs?]
end
Unfortunately, unlike some languages, Ruby doesn't have such a construct. Fortunately, it does have
the facilities to create one. I thought there was already an implementation, but I couldn't find it at
first. So I started to write my own.
For some reason I was looking through
Utility Belt and noticed
it had an implementation of
with()
:
class Object
def with(object, &block)
object.instance_eval &block
end
end
Unbelievable! My implementation was running into a WTF in its own right, and here was this one-liner.
Unfortunately, Utility Belt's
with()
didn't pass the
test cases that demonstrate
how I wanted to use it, so I had to move on.
With was created as a result of those efforts. It
works how I want it to in the simple cases I've demonstrated. It still needs some work on left-hand-side
variables that are not members of the aforementioned
@foo
. It needs some tests for
more complex uses like nested blocks (and
code to make them pass). But it works for what I imagine the majority usage would be.
I opted for the syntax
With.object(foo) do ... end
so as to not
force you to use a
change to
Object
. However, you can
require 'with_on_object'
if you prefer
to just use
with(@foo)
. There's also a conditional patch on
NilClass
if
empty?
does not exist. It is added and removed in the same method.
It requires
Ruby2Ruby and
ParseTree
to do its magic, though that will change soon due to compatibility problems with Ruby 1.9 and other implementations
(for which another project exists, if I've read correctly).
To install, you can use:
sudo gem install codeodor-with -s http://gems.github.com
Let me know if you're using it and encounter any problems. I'd like to fix them quickly, if I can.
Hey! Why don't you make your life easier and subscribe to the full post
or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate
wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!