Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Monday, November 21, 2011

Ruby module instance and class methods

A very common idiom especially when code starts to become complicated is to put functions in modules and mix in that behavior to several classes.  And a common expansion is to have a single "include" add both instance and class methods.

Here is how to do it:


"include" is used to add a module's instance methods as instance methods to the including class, but it doesn't traverse sub modules.  "extend" is used to add a module's instance methods as class methods to a class.

When a module is "included" it can register a callback which is passed the class that is doing the including.  And calling "extend" on the base and passing a submodule will cause it to put those methods at the class level.  This causes a chain reaction of loading both instance and class methods using a single "include".

Pro Tip: It is possible to cause the same behavior using "extend" by using the "extended" callback; however, this is not common and "include 'x'" reads better then "extend 'y'".

Wednesday, May 11, 2011

Cucumber with using Rspec should_receive

I recently came across a case where I wanted to use a should_receive test in cucumber. The basic idea is that I was attempting to prevent Apache library code from calling out to the system, while simultaneously testing that the correct function was actually called. In Rspec (which backs cucumber in my setup) it is simply:



At the end of the test if restart has not been called then the entire test fails. Because of the way that cucumber works with rspec 1.3 (rails 2.x, which is required by the project) registering a should_receive has no effect (seems this is fixed in the cucumber/rspec versions for rails 3). Even if it were to work it would mean putting a Then before the When or putting a test in a Given. To me that just seems wrong.



What I had to do to simulate a should_receive but still maintain the flow of the scenario was break it up so that I stub the function and when that function is called I set a flag. Later I test that the flag is set.



The step that sets the flag is Apache can restart and the one that tests is Apache should restart. Here are the step definitions: