# Using model methods for repetitive finds

**URL:** <https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678>\
**Category:** Rails\
**Created:** [September 22, 2006, 9:42pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678 "2006-09-22T21:42:24Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 9:42pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/1 "2006-09-22T21:42:24Z")

</div>

i am still fairly new to rails and am trying to write methods in the  
model for finds that i will need to use over and over.

in my Task model i have:

def self.most\_recent\_tasks  
find(:all, :order =\> ‘updated\_at DESC’, :limit =\> 10)  
end

this works great when i try something like Task.most\_recent\_tasks, but  
is there a way to rewrite it so that i can use this method on a  
collection of tasks too? i don’t know if i need to write a separate  
method to be able to do something like:

josh.tasks.most\_recent\_tasks

or if there is a way to write one that works for both.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 10:02pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/2 "2006-09-22T22:02:26Z")

</div>

After playing around with it a little more I am using this:

def self.most\_recent(tasks = self)  
tasks.find(:all, :order =\> ‘updated\_at DESC’, :limit =\> 10)  
end

now I can use something like:

Task.most\_recent()

AND

Task.most\_recent(josh.tasks)

although this works, i would really like to hear from other developers  
and see if this would be the recommended way of doing something like  
this.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 10:22pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/3 "2006-09-22T22:22:27Z")

</div>

See the association extensions section of the API near the top of this  
page. Should let you do exactly what you’re wanting.

> **[ActiveRecord::Associations::ClassMethods](https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html)**
>
> Associations are a set of macro-like class methods for tying objects together through foreign keys.

Something like…

Class Josh \< ActiveRecord::Base  
has\_many :tasks do  
def most\_recent(n)  
Find.tasks(:all, :order =\> ‘updated\_at DESC’, :limit =\> n)  
end  
end  
end

josh.tasks.most\_recent(42) =\> array of 42 most recently updated  
tasks.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 10:52pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/4 "2006-09-22T22:52:30Z")

</div>

Hello Josh,

> is there a way to rewrite it so that i can use this method on a  
> collection of tasks too? i don’t know if i need to write a separate  
> method to be able to do something like:
> 
> josh.tasks.most\_recent\_tasks
> 
> or if there is a way to write one that works for both.

First solution : you can add another association to your model  
like this.

class Person \< AR::B  
has\_many :tasks  
has\_many :most\_recent\_tasks, :class\_name =\> ‘Task’,  
order =\> ‘updated\_at DESC’, :limit =\> 10  
end

So you could have josh.tasks and josh.most\_recent\_tasks

Second solution, you can use association extension, that  
is, you define additional methods in a block for your has\_many  
association :

class Person \< AR::B  
has\_many :tasks do  
def most\_recent\_tasks(n = 10)  
find :all, :order =\> ‘updated\_at DESC’, :limit =\> n  
end  
end  
end

josh.tasks.most\_recent\_tasks  
or josh.tasks.most\_recent\_tasks(20)

Note that you can put your definition in a module :

class Person \< AR::B  
has\_many :tasks, :extend =\> Stuff  
end

and most\_recent\_tasks is in module Stuff.

– Jean-FranÃ§ois.

–  
Ã? la renverse.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 10:56pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/5 "2006-09-22T22:56:31Z")

</div>

Thanks for the replies.

Is there any specific reason why it would be better to keep this in the  
User model instead of just having it in my Task model?

One of the reasons I was trying to do it this way was so I could just  
put:

“Task.most\_recent” and find ALL of the most recent tasks and then still  
use the same method for individual users and put  
“Task.most\_recent(josh.tasks)”

I see how the methods you have posted would help a lot if I was only  
finding a collection of tasks relating to the user, but with mine, i  
could pass any collection i wanted or just not give it any paramters to  
search the entire database.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 11:42pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/6 "2006-09-22T23:42:34Z")

</div>

beautiful! that’s exactly what i’m looking for! thanks

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 11:34pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/7 "2006-09-22T23:34:32Z")

</div>

Hi again Josh,

> Is there any specific reason why it would be better to keep this in the  
> User model instead of just having it in my Task model?
> 
> One of the reasons I was trying to do it this way was so I could just  
> put:
> 
> “Task.most\_recent” and find ALL of the most recent tasks  
> and then still use the same method for individual users and put  
> “Task.most\_recent(josh.tasks)”

but your definition :

def self.most\_recent(tasks = self)  
tasks.find(:all, :order =\> ‘updated\_at DESC’, :limit =\> 10)  
end

works but is quite ugly, in the sense it’s not the Ruby way.

If you want to share your AR query, put it in a module, then mix  
it in the classes you want :

module Stuff  
def most\_recent(n = 10)  
find :all, :order =\> ‘updated\_at DESC’, :limit =\> n  
end  
end

class User \< AR::B  
class \<\< self  
include Stuff  
end

has\_many :tasks, :extend =\> Stuff  
end

class Task  
class \<\< self  
include Stuff  
end  
end

class Comment \< AR::B  
class \<\< self  
include Stuff  
end  
end

Then you can do Comment.most\_recent, josh.tasks.most\_recent  
Task.most\_recent, Task.most\_recent(20)

Modules are the way to make it DRY.

> I see how the methods you have posted would help a lot  
> if I was only finding a collection of tasks relating to the user,  
> but with mine, i could pass any collection i wanted or just  
> not give it any paramters to search the entire database.

and with your method, sth like Task.most\_recent(Comment)  
would return the last recent comments, but since Comment model  
is not necessarily related to Task model, this is quite ugly for me !

Regards,

```
-- Jean-FranÃ§ois.

```

–  
Ã? la renverse.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 23, 2006, 12:04am UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/8 "2006-09-23T00:04:36Z")

</div>

2006/9/22, Josh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ok i’m sorry for this one, but where is the best place to put modules  
> so that i can do this?

This module is model-related so app/models is OK for me.

– Jean-FranÃ§ois.

–  
Ã? la renverse.

---

<div class="post-metadata">

**Author:** ![jjkiesch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bc79bd/32.png) [@jjkiesch](https://www.ruby-forum.com/u/jjkiesch)\
**Post date:** [September 22, 2006, 11:50pm UTC](https://www.ruby-forum.com/t/using-model-methods-for-repetitive-finds/69678/9 "2006-09-22T23:50:35Z")

</div>

ok i’m sorry for this one, but where is the best place to put modules  
so that i can do this?
