0

I have a module that has a few methods that help find database entries, and I'm trying to create dynamic methods of this sample method:

def find_by(db_attribute, value)
  rows = connection.execute <<-SQL
    SELECT #{columns.join ","} FROM #{table}
    WHERE #{db_attribute} = #{Record::Utility.sql_strings(value)};
  SQL
end

I want to figure out how to get a call object.find_by_*( * star here being the db_attribute that would normally be in the parameter of find_by) like this: klass.find_by_name('bob') to return the same thing as find_by(:name, 'bob').

0

1 Answer 1

3

A very simple solution

def method_missing(method_name, *args, &block)
  if method_name.to_s =~ /^find_by_(.+)$/
    find_by($1.to_sym => args)  # find_by_name, the $1 is `name`
  else
    super(method_name, *args, &block)
  end
end
Sign up to request clarification or add additional context in comments.

5 Comments

Wow this is all I needed? when I was googling for the answer I came across so many guides that confused the heck out of me. Many articles said it was a good idea to also update respond_to? when you redefine method_missing, and I saw others also using alias and alias_method. I wasn't sure what I needed to do, thanks
technically this should be find_by($1, *args) to match the method signature as well as to avoid the args Array becoming a string value in the query. Additionally the call to super does not need the explicit argument passing (but this is more a quibble than anything else)
@WolfgangTruong: Yes, whenever you implement method_missing, you should always also implement respond_to_missing? accordingly. respond_to will ask respond_to_missing?, and thus properly respond with true even for message to non-existing methods that are handled dynamically.
@WolfgangTruong: One of the reasons those guides look more complex than this, is that this answer doesn't dynamically create methods. It only dynamically handles messages, which is much simpler. If you searched for guides to dynamically create methods, then they will of course have been much more complex. I am not sure why you are asking about dynamically creating methods, and then accept an answer that doesn't do that. Obviously, dynamically creating methods is not required to solve your problem.
@JörgWMittag I mean it kind of does create dynamic methods... Because now I can call any find_by_* method and it'll uses my find_by method to find the record. its not ONLY handling messages, its also redirecting any method find_by_ call to the find_by() method. I guess you could argue that my question could be titled differently, I'm just happy its solved :D.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.