Dynamic Finders
Make your model calls more readable by using dynamic finders.
With the recent introduction of onMissingMethod() in ColdFusion 8 (Thanks, Adobe!), we have been able to port over the concept of dynamic finders from Rails to Wheels.
The concept is simple. Instead of using arguments to tell Wheels what you want to do, you can use a dynamically-named method.
For example, the following code:
<cfset me = model("user").findOne(where="email='me@myself.com'")>
Can also be written as:
<cfset me = model("user").findOneByEmail("me@myself.com")>
Through the power of onMissingMethod(), Wheels will parse the method name and figure out that the value supplied is supposed to be matched against the email column.
Dynamic Finders Involving More than One Column
You can take this one step further by using code such as:
<cfset me = model("user").findOneByUserNameAndPassword("bob,pass")>
In this case, Wheels will split the function name on the And part and determine that you want to find the record where the username column is "bob" and the password column is "pass".
When you are passing in two values, make special note of the fact that they should be passed in as a list to one argument and not as two separate arguments.
Works with findAll() too
In the examples above, we've used the findOne() method, but you can use the same approach on a findAll() method as well.
Passing in Other Finder Parameters
In the background, these dynamically-named methods just pass along execution to findOne() or findAll(). This means that you can also pass in any arguments that are accepted by those two methods.
The below code, for example, is perfectly valid:
<cfset users = model("user").findAllByState(value="NY", order="name", page=3)>
When passing in multiple arguments like above, you have to start naming them instead of relying on the order of the arguments though. When doing so, you need to name the argument value if you're passing in just one value and values if you're passing in multiple values in a list. In other words, you need to name it values when calling an And type dynamic finder.
<cfset
users = model("user").findAllByCityAndState(
values="Buffalo,NY", order="name", page=3
)
>
Avoid the Word "And" in Database Column Names
Keep in mind that this dynamic method calling will break down completely if you ever name a column firstandlastname or something similar because Wheels will then split the method name incorrectly. So avoid using "And" in the column name if you plan on taking advantage of dynamically-named finder methods.
Comments
Read and submit questions, clarifications, and corrections about this chapter.

Does this mean I shouldn't have a column named "operand"?
Would I also be able to use the OR operator like findOneByUsernameOrEmail(params.user.login)?
Ezra,
You can name a column "operand," but you will not be able to use a dynamic finder like findOneByUsernameAndPassword because Wheels would not be able to parse it properly. Everything else in the ORM should work just fine though.
Dave,
That is not currently supported. Feel free to submit a feature request in our Issue Tracker:
http://code.google.com/p/cfwheels/issues/list
When passing a list in code such as
<cfset me = model("user").findOneByUserNameAndPassword("#foo#,#bar#")>
it seems like this would break if there was a comma in the variable foo? Is there a way to specify a different delimiter that users would be less likely to have input in the database or whatever?
Also, your CAPTCHAs are extremely difficult to read...this is my second try....
Chris: If you passed a string value, you'd need to put quotes around it anyway, like this:
<cfset me = model("user").findOneByUserNameAndPassword("'#foo#','#bar#'")>
There was a related issue to what you've described, and we've since fixed it. It shouldn't be a problem now if you're using the latest version.