How to filter find(:all)


#1

We’re going to be changing our system soon to implement the concept of
a trash can. Basically when user deletes things they will get flagged
as ‘trash’ and won’t be deleted until the user goes into the trash
area and explicitly deletes them. The way we’ll do this is set a field
in the tables, say ‘trash’ to 1 if trashed, 0 if active.
What I don’t want to have to do though is go back and change every
line like

Posts.find(:all)

to something like

Posts.find(:all, :conditions => ‘trash = 0’)

as I’m sure it will get very messy. Is there someway to do this in the
model so that generally only active posts get returned while the
trashed stuff requires a specific call - say something like

Posts.find_trashed(:all)

or

Posts.find_trashed(‘123’)

Thanks for any help on this.

Dale


#2

On Wed, Mar 14, 2007 at 01:17:36AM -0700, PeteSalty wrote :

Is there someway to do this in the
model so that generally only active posts get returned while the
trashed stuff requires a specific call - say something like

Posts.find_trashed(:all)

or

Posts.find_trashed(‘123’)

Sure!
In your Post model:

def self.find_trashed
find(all, :conditions => [‘trashed = 1’])
end

Do the same with find_untrashed, etc.

I never put such business logic in my controllers. Whenever I am tempted
to write Post.find(:all, :conditions => …), I define a new class
method
(self.) in my model. The code is really cleaner.

My $0.02


,========================.
| Pierre-Alexandre M. |
| email : removed_email_address@domain.invalid |
`========================’


#3

Take a look at acts_as_paranoid (http://ar-paranoid.rubyforge.org/) -
somewhat
of an overkill for your scenario, but the ideas are similar. Using a
similar
strategy will let you keep all your normal find(:all) calls as they are.

–mdj

On 3/14/07, PeteSalty removed_email_address@domain.invalid wrote:

or

Posts.find_trashed(‘123’)

Thanks for any help on this.

Dale


Matt J.
removed_email_address@domain.invalid
President/Technical Director, Acme Art Company (acmeartco.org)


#4

if you have a ‘trashed’ column in your database, you will have a
trashed attribute in your model. Rails will automatically add finders
for all the attributes in your model.

so you will have access to

find_by_trash() # finds first where trash =
find_all_by_trash() #f finds all where trash =


#5

I would go with the method approach (using find_by_sql or find), as
dynamic finders will cost you performance wise

ex.

def find_active_posts
find(all, :conditions => [‘trashed = 0’])
end

def find_trashed
find(all, :conditions => [‘trashed = 1’])
end


#6

Whoops, maybe I wasn’t clear here - the idea is to NOT write the
find_untrashed function. It’s to have find(:all) (or any other
variation of the standard find procedures) return only the non-trashed
items.


#7

I’d say the performance hit is negligible

PartSearch.count
=> 99588

puts Benchmark.measure { PartSearch.find_all_by_part(‘lm311’) }
0.033333 0.000000 0.033333 ( 0.296591)
=> nil

puts Benchmark.measure { PartSearch.find(:all, :conditions =>
[“part = ?”, “lm311”]) }
0.000000 0.000000 0.000000 ( 0.233105)
=> nil

puts Benchmark.measure { PartSearch.find(:all, :conditions => “part
= ‘lm311’”) }
0.000000 0.000000 0.000000 ( 0.348846)
=> nil