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…?
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.
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
@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.