# Changing find method

**URL:** <https://www.ruby-forum.com/t/changing-find-method/102027>\
**Category:** Rails\
**Created:** [August 9, 2006, 12:25pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027 "2006-08-09T12:25:10Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 9, 2006, 12:25pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/1 "2006-08-09T12:25:10Z")

</div>

Hi,

i was wondering if there was a nice clean way(after all, it is ruby) to  
change the find method of a certain model/class (Page) so that if i  
wanted to use a find method on a @page instance it would return only  
specific rows from the table(if the page.published == true/false:

the pages table looked like  
SQL:

…  
id int not null auto\_increment,  
published tinyint(1) not null,  
something varchar not null,  
…  
end of table

and i had a query:

@page = Page.find(:all)

it would return only the pages that had pages.published == true.  
i thought the def would be something like:

Class Page \< ActiveRecord::Base

def find  
super  
self.find(:all, :conditons =\> ‘published=1’)  
end

but it isn’t working.  
could possibly do

def find\_published  
self.find(:all, :conditons =\> …)  
end

and change all of my find methods to @page.find\_published…?  
am i going down the wrong train of thought? where/how do i change a  
class method to my own needs without ruining the initial method…?

?

thanks for any reference,

harp

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 10, 2006, 1:35am UTC](https://www.ruby-forum.com/t/changing-find-method/102027/2 "2006-08-10T01:35:41Z")

</div>

class Page …

def self.find(…)  
end

end

don’t call super as this will call ActiveRecord’s find only to call it  
again  
when you explicitly call it (in the next line)

cheers

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 10, 2006, 12:10pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/3 "2006-08-10T12:10:03Z")

</div>

> don’t call super as this will call ActiveRecord’s find only to call it  
> again  
> when you explicitly call it (in the next line)  
> (recursive loop?) …ok.

a little more detailed description of this issue:

i want to define the find method for a Page model.  
if an admin is logged on to the site(i.e, @session[‘admin’]!=nil)i want  
him to see all of the pages in the ‘pages’ table, but if a regular user  
uses the application i only want him to see the pages that are defined  
with pages.publish = 1/true (discarding all of the rows that have  
publish=0/false).

i suppose i could do this via going into every action displaying @pages  
= Page.find(:…:conditons =\> ‘publish=1’…etc) but there are a couple  
good places i need to do this, and aside from it being more DRY, it is  
also a much more asthetic solution to do it via the model(it should be  
beautiful).

…but like many of the beautiful solutions, the way getting there is  
pretty ugly; i’ve tried taking the ‘find’ source-code from activerecord  
and modifiying it, but truthfully enough, it hasn’t led anywhere  
important, aside from wasting me a great deal of time…

```
    def self.find(*args)
 	records = []
 	options = extract_options_from_args!(args)
	validate_find_options(options)
	set_readonly_option!(options)
	case args.first
	  when :first then records = find_initial(options)
	  when :all then records = find_every(options)
	  else records = find_from_ids(args, options)
	end
	records.each { |record| record.publish==1}
	records
 end

```

…is there a simpler way to do this? i even dug dipper and tried  
changing the ‘find\_initial’, ‘find\_every’, and ‘find\_from\_ids’ methods,  
but then i realized i was running around in circles and not really  
getting anywhere substansial.

any ideas?  
many thanks,

harp

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 10, 2006, 8:22pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/4 "2006-08-10T20:22:51Z")

</div>

harper wrote:

> and change all of my find methods to @page.find\_published…?  
> am i going down the wrong train of thought? where/how do i change a  
> class method to my own needs without ruining the initial method…?

def self.find(args)  
self.with\_scope(:find =\> { :conditions =\> “published = 1” }) do  
super(args)  
end  
end

Usual caveats for code written in an email and not tested apply 🙂

–  
Josh S.  
[http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 10, 2006, 8:49pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/5 "2006-08-10T20:49:58Z")

</div>

thanks!!!

beautiful. i should get more into the whole “scope” issue…i have never  
really used it; and it seems important enough…

in much debt. thanks again,

harp

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 10, 2006, 8:06pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/6 "2006-08-10T20:06:15Z")

</div>

is there any way to do this??? or am i just wasting my time??

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 15, 2006, 2:15pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/7 "2006-08-15T14:15:46Z")

</div>

in application\_controller.rb

def get\_pages  
if session[:admin]  
@pages = Page.find :all  
else  
@pages = Page.find\_all\_by\_publish(1)  
end  
end

Then in your controllers

before\_filter :get\_pages, :only =\>[:list, :index, :some\_other\_action]

def list

# @pages should already be filled from before\_filter so no need to do

it  
here.  
end

That should work for you I think… It’s a bad idea to do things like  
that  
in the model because they’re related to session… MVC likes separation  
of  
business rules from flow control.

---

<div class="post-metadata">

**Author:** ![harper](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/b5ac83/32.png) [@harper](https://www.ruby-forum.com/u/harper)\
**Post date:** [August 15, 2006, 2:19pm UTC](https://www.ruby-forum.com/t/changing-find-method/102027/8 "2006-08-15T14:19:22Z")

</div>

Sounds messy. Maybe you need to use  
with\_scope[http://www.codyfauser.com/articles/2006/02/01/using-with\_scope-to-refactor-messy-finders](http://www.codyfauser.com/articles/2006/02/01/using-with_scope-to-refactor-messy-finders)  
.

## Hope that suffice

choonkeat

- [http://blog.yanime.org/](http://blog.yanime.org/)
- [http://www.rssfwd.com/](http://www.rssfwd.com/)
