Incorporating runtime parameters in has_many :conditions

Matt Westcott wrote:

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 )

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.

Mark Reginald James wrote:

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

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