Model.find_by_attribute only called the first time

# This is a sanitized example of what I am doing at work and was perplexed

def Person.find_by_name(*params)     puts "hello world!"     params.first.chop! if params.first.last == "."     super end

# It strips the trailing . and puts hello world!

Person.find_by_name("Chris.")

"hello world!" => #<Person id: 1, :name: "Chris">

# I hit up arrow and enter

=> nil

# Why is the method not actually being called the second time? # I can handle never working and always working, but always working once I can't handle.

Thanks, Chris Lundquist

May I suggest aliasing the method instead of trying to call super?

alias_method :old_find_by_name, :find_by_name

def Person.find_by_name(*params)

params.first.chop! if params.first.last == “.”

old_find_by_name(params)

end

May I suggest aliasing the method instead of trying to call super? alias_method :old_find_by_name, :find_by_name def Person.find_by_name(*params) params.first.chop! if params.first.last == "." old_find_by_name(params) end

super won't work here because the method isn't defined on a parent of Person, it's defined on person itself. So what's happening is that the call to method missing is generating a *new* implementation of find_by_name which simply does the find, without your changes.

We could fix this for rails 3.0 by moving those generated methods from Person to a module included in person, but for 2.3 you'll have to do as Ryan suggests and use aliasing, or just call all(:conditions=>{:first_name=>params.first}) instead of super.

Koz and Ryan,

Now that you point it out, I see how #method_missing calls find, then find thinks I'm retarded and over writes my method by doing a class eval. Thus removing my original code.

Am I figuring that right?

I've always had trouble generating aliases to singleton methods.

I seem to recall the following syntax doesn't work alias self.old_name self.new_name

but I might be confusing trying

alias old_name self.new_name

Thank you for your insights, Chris Lundquist

I’ve just realised that because this is a dynamic finder the “power” of method_missing is what’s going to stop you from being able to alias this method. This method appears to not be defined until method_missing catches it and defines it then. I’ve tried also calling the method before aliasing it (thereby defining it) but without much luck:

user.rb:

find_by_name(nil)

class_eval do

alias_method :old_find_by_name, :find_by_name

end

NameError: undefined method find_by_name' for class User’

I’m really interested in how this would be done now.

I just wanted a :before_find hook, saw the mail history from here during 2006 and they said do

def find # Before Find. super # After Find end

But now we know how that turns out.

Ultimately it isn't important to my app, but it would be nice when me or users forget trailing .s

Thanks, Chris Lundquist

You might also want to think about doing this in a before_filter; cleaning trailing spaces off of request parameters feels pretty controller-y to me.

--Matt Jones

I'm working with BIND files and DNS. Sometimes the method isn't called from a controller. Sometimes it will be called from a cron tab and script/runner