# Metaprogramming oddness - works in console but fails in spec

**URL:** <https://www.ruby-forum.com/t/metaprogramming-oddness-works-in-console-but-fails-in-spec/166295>\
**Category:** Rails\
**Created:** [April 23, 2009, 4:57pm UTC](https://www.ruby-forum.com/t/metaprogramming-oddness-works-in-console-but-fails-in-spec/166295 "2009-04-23T16:57:52Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [April 23, 2009, 4:57pm UTC](https://www.ruby-forum.com/t/metaprogramming-oddness-works-in-console-but-fails-in-spec/166295/1 "2009-04-23T16:57:52Z")

</div>

Hi folks

Let’s say i have these methods, and i want to abstract them into a bit  
of metaprogramming, for dryness’ sake:

def water\_score\_for(year)  
self.send(“ratings.water.#{year}.collect(&:score).sum”)  
end

def possible\_water\_score\_for(year)  
self.ratings.water.#{year}.size \* 2  
end

def sanitation\_score\_for(year)  
self.send(“ratings.sanitation.#{year}.collect(&:score).sum”)  
end

def possible\_sanitation\_score\_for(year)  
self.ratings.sanitation.#{year}.size \* 2  
end

I’m trying to do this via ‘define\_method’: here’s my code:

#defined elsewhere  
#PolicyIndicator::SECTORS = [“water”, “sanitation”]

PolicyIndicator::SECTORS.each do |sector|  
self.send(:define\_method, “#{sector}_score\_for".to\_sym) do |year|  
self.send(“ratings”).send("#{sector}").send("for_#{year}”).collect(&:score).sum  
end

```
self.send(:define_method, "possible_#{sector}_score_for".to_sym) do

```

|year|  
self.send(“ratings”).send("#{sector}").send(“for\_#{year}”).size \*  
2  
end  
end  
Now, this works fine in the console:

> > country = Country.find(:first)  
> > =\> #\<Country id: 1, region\_id: 1, name: “Nigeria”, created\_at:  
> > “2009-04-21 08:39:09”, updated\_at: “2009-04-22 16:24:29”,  
> > sanitation\_coverage: 62.0, water\_coverage: 45.0, hdi: 0.405497,  
> > population\_millions: 46.0, child\_mortality: 52.0, gdp: 13724.8\>

> > country.water\_score\_for(2009)  
> > =\> 9

But when i run a spec that makes a country, makes some ratings,  
associates them with the country and call the method on it, i get this  
error back:

undefined method `for_2009' for #<Array:0xb70cd19c> ( __DELEGATION__ ):2:in` **send** ’  
( **DELEGATION** ):2:in `with_scope' ( __DELEGATION__ ):2:in` **send** ’  
( **DELEGATION** ):2:in `with_scope' /home/max/work/washwatch_container/washwatch/app/models/country.rb:11:in`send’

the line (country.rb:11) in question is this:  
self.send(“ratings”).send("#{sector}").send(“for\_#{year}”).collect(&:score).sum

It seems to be falling over on the named scopes on the Rating class, so  
i guess maybe i’m not using ‘send’ int he optimal way. However, it  
seems to work perfectly in the console - checking my log file, the  
correct, optimised sql query is being called.

Can anyone help?  
thanks  
max
