# Incorporating runtime parameters in has\_many :conditions

**URL:** <https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450>\
**Category:** Rails\
**Created:** [November 28, 2006, 1:37am UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450 "2006-11-28T01:37:04Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 28, 2006, 1:37am UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450/1 "2006-11-28T01:37:04Z")

</div>

Hi,  
I was wondering if there was any way to include runtime parameters in  
the :conditions clause of a has\_many relationship?

I’m trying to model the concept of a person who goes by various  
nicknames. My Person model contains a “name” attribute containing their  
real name, and a “has\_many :nicknames” relationship. Through my business  
rules, I’m enforcing the requirement that a person’s real name is always  
included in the database as a nickname.

(If this seems like a really bad data structure, I’m open to  
suggestions. However, having weighed up various alternatives, this seems  
to me to be the least worst solution.)

I now want to add an “alternative\_nicknames” relationship, which will  
comprise all of the person’s nicknames _excluding_ their real name. I’ve  
tried

has\_many :alternative\_nicknames, :class\_name =\> “Nickname”,  
:conditions =\> [“nickname \<\> ?”, self.name]

- however, since has\_many is a class-level method, the :conditions block  
is evaluated at the point of loading the class, and therefore self.name  
returns “Person” rather than the person’s name. Out of desperation I’ve  
even tried wrapping the has\_many declaration in an after\_initialize  
callback, but then it complains that has\_many is not defined. The  
examples in the Rails docs and the Pragmatic book only demonstrate  
static SQL fragments being used in the :conditions clause, not ones  
incorporating parameters. Any ideas how I can achieve this?

(If it helps explain things any better, I believe this person’s  
(unanswered) question is equivalent to mine:  
[http://groups.google.com/group/rubyonrails-talk/msg/5006b300e4e5a8cc](http://groups.google.com/group/rubyonrails-talk/msg/5006b300e4e5a8cc) )

- Matt

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 28, 2006, 12:04pm UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450/2 "2006-11-28T12:04:38Z")

</div>

Matt Westcott wrote:

> incorporating parameters. Any ideas how I can achieve this?
> 
> (If it helps explain things any better, I believe this person’s  
> (unanswered) question is equivalent to mine:  
> [http://groups.google.com/group/rubyonrails-talk/msg/5006b300e4e5a8cc](http://groups.google.com/group/rubyonrails-talk/msg/5006b300e4e5a8cc) )

Write the condition with single quotes to delay evaluation until  
the association load is done in an instance context:

```
:conditions => 'nickname <> #{name}'

```

This assumes a sanitized name attribute. If name is instead stored  
in an unsanitized form you can try something like:

:conditions =\> ‘nickname \<\> #{class.connection.quote(name)}’

It would have been nice to be able to write

:conditions =\> ‘[“nickname \<\> ?”, #{name}]’

but conditions are currently sanitized then interpolated, not  
interpolated then sanitized, and to make the reverse work  
interpolation would have to be changed to handle arrays.

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 28, 2006, 4:09am UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450/3 "2006-11-28T04:09:38Z")

</div>

On Nov 27, 2006, at 4:37 PM, Matt Westcott wrote:

> I’m trying to model the concept of a person who goes by various  
> nicknames. My Person model contains a “name” attribute containing  
> their  
> real name, and a “has\_many :nicknames” relationship. Through my  
> business  
> rules, I’m enforcing the requirement that a person’s real name is  
> always  
> included in the database as a nickname.

Rule #1: If you’re duplicating data, you’re doing the wrong thing,  
unless  
you have a VERY SERIOUS performance problem and you have  
measured  
the performance advantage of a denormalization very carefully.

> (If this seems like a really bad data structure, I’m open to  
> suggestions.  
> However, having weighed up various alternatives, this seems to me  
> to be the  
> least worst solution.)

I’d recommend either:

1. Not storing their real name in nicknames.

or

1. Removing the “name” attribute from Person and adding an extra  
attribute  
to your Nicknames model named real\_name that is a boolean.

I prefer #1 because real names are decided NOT nicknames, so why  
would they  
be stored there?

If you like #2, then I’d highly recommend renaming that model Names,  
because  
they’ll decidedly NOT be just nicknames any longer!

I find a lot of DB designers paint themselves into corners by doing  
the sort  
of thing that you’ve done here. If the tables names don’t fit the  
use, it’s  
not that you have a special need, it’s because your data model is  
wrong. 🙂

If the data model is wrong, you’re going to write a larger volume of  
code, and  
even worse, a larger volume of _complex_ code to ‘decipher’ the data  
that will  
become hopelessly entangled over time.

> I now want to add an “alternative\_nicknames” relationship, which will  
> comprise all of the person’s nicknames _excluding_ their real name.  
> I’ve  
> tried

With the advice above, there’s no need to do this. In #1 real name is  
one place  
and nicknames are another place, or in #2 the two are very obviously  
separate  
via the boolean column which will make it easier to pinpoint real  
names -vs-  
nicknames.

> callback, but then it complains that has\_many is not defined. The  
> examples in the Rails docs and the Pragmatic book only demonstrate  
> static SQL fragments being used in the :conditions clause, not ones  
> incorporating parameters. Any ideas how I can achieve this?

There’s nothing magic in the _operation_ of has\_many for the simplistic  
cases, so you _could_ leave out the has\_many declaration and just code  
an accessor method of your own:

def alternative\_nicknames  
self.nicknames.find(:all, :conditions =\> [“nickname \<\> ?”,  
self.name])  
end

One thing I think you need to be a bit skeptical of, however, is in the  
clear overloading of the Nicknames.nickname column. You’re not just  
storing a nickname there, but through usage, you’re also using it to  
define a boolean relationship as well, based on variable data in the  
parent table.

If you use method #1 above, you could access the various pieces very  
simply and without any sort of magic at all.

person.name  
person.nicknames  
person.all\_names

class Person  
def all\_names  
[name,nicknames.collect { |n| n.nickname}]  
end  
end

–  
– Tom M., CTO  
– Engine Y., Ruby on Rails Hosting  
– Reliability, Ease of Use, Scalability  
– (866) 518-YARD (9273)

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 29, 2006, 12:50am UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450/4 "2006-11-29T00:50:41Z")

</div>

Tom M. wrote:

> On Nov 27, 2006, at 4:37 PM, Matt Westcott wrote:
> 
> > I’m trying to model the concept of a person who goes by various  
> > nicknames. My Person model contains a “name” attribute containing  
> > their  
> > real name, and a “has\_many :nicknames” relationship. Through my  
> > business  
> > rules, I’m enforcing the requirement that a person’s real name is  
> > always  
> > included in the database as a nickname.
> 
> I’d recommend either:
> 
> 1. Not storing their real name in nicknames.  
> or
> 2. Removing the “name” attribute from Person and adding an extra  
> attribute  
> to your Nicknames model named real\_name that is a boolean.

Excellent, thanks - that does make a lot of sense. (Option 2 makes more  
sense in my case, as I’ve got other models in the system which define  
relations with (nick)names, so I need to keep them all together.) I  
think this is one of those occasions where I’m so hung up over a niggly  
detail of the data model that it takes another pair of eyes to see the  
obvious solution… cheers.

Mark Reginald J. wrote:

> Write the condition with single quotes to delay evaluation until  
> the association load is done in an instance context:  
> :conditions =\> ‘nickname \<\> #{class.connection.quote(name)}’

Thanks for this too - good to know the direct answer for when I need it  
in future. I have to admit that my paranoid side is now wondering if  
it’s really doing two passes of evaluation (and if so, what happens if  
your data itself contains “#{insert malicious ruby code here}”) but I’m  
sure it’ll all make sense to me after an hour or two of head-scratching  
🙂

- Matt

---

<div class="post-metadata">

**Author:** ![mwalsh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@mwalsh](https://www.ruby-forum.com/u/mwalsh)\
**Post date:** [November 28, 2006, 2:16pm UTC](https://www.ruby-forum.com/t/incorporating-runtime-parameters-in-has-many-conditions/77450/5 "2006-11-28T14:16:55Z")

</div>

Mark Reginald J. wrote:

> ```
> :conditions => 'nickname <> #{name}'
> 
> ```

Oops, scrub this, name isn’t quoted. Use this insead

> :conditions =\> ‘nickname \<\> #{class.connection.quote(name)}’

–  
We develop, watch us RoR, in numbers too big to ignore.
