[rspec-users] Issue with parameterized shared example group on ruby 1.8.6

Myron Marston myron.marston at gmail.com
Fri Aug 20 14:43:02 EDT 2010


> 1.  Find a better way to fake module_exec on ruby 1.8.6.  I'm not sure
> if this is even doable.

Actually, after thinking about this some more, I think I've come up
with a solution that will eliminate the error I'm seeing, but it's not
a perfect solution.  Let me see if I can explain this well...

Given this block:
do
  def m1; end
  def self.m2; end
end

When it is evaluated using instance_eval, both m1 and m2 get defined
as singleton methods on the object that is the receiver of
#instance_eval.  When the receiver is a class or module, these will
both be class methods (since class methods are simply singleton
methods on a class or module object).

When it is evaluated using module_eval, m1 becomes an instance method
and m2 becomes a class method--just like how method definitions work
in a class or module body.

So...the entire reason for the module_eval (which is where the error
occurs) is to distinguish between instance method definitions and
class method definitions, so that we can remove m1 as a class method
and add it as an instance method.  With instance_eval we have no way
to tell which are which, since all definitions become class methods.

My idea for an alternate approach is to only do the instance_eval, and
then duplicate all new class methods as instance methods (since some
of them may have been defined using "def method_name").  Then the
module_eval is no longer needed.  There are a few downsides to this,
though:

* All methods defined in the block become both class _and_ instance
methods.  Someone could accidentally call the method the wrong way
(i.e. call what should have been an instance method on the class, or a
class method on an instance), and while this may work on ruby 1.8.6
(depending on the code), it would fail on 1.8.7 and above.
* There's the possibility to stomp an existing instance method
definition.  For example, consider the block given above.  If there
was already an m2 instance method that had different logic, it would
get stomped here, since we would be defining an m2 instance method
with the logic of the m2 class method.

I think this is probably the best solution, but I want to hear what
others (particularly David) think.

Thanks,
Myron


More information about the rspec-users mailing list