Users can upload photos (and possibly videos, music etc. in future)
each of which must be approved by an administrator before it becomes
public. The photos are being displayed in a multitude of views
(search, best photos, user profile, random photo, recently added
photos etc.) of which each (except the photo owner’s private view and
some administrative views) must only display photos that have been
approved by an administrator. That means in every of those actions, I
have to specify :conditions => ‘approved is true’ which is not DRY at
all, which is error prone etc.
Does anyone know of a good solution to this?
Erik
P.S. I’ve also thought of a solution in which unapproved/rejected
photos reside in a different table, which would also be a little
better performing for most select queries but adds complexity to the
domain model.
P.S. I’ve also thought of a solution in which unapproved/rejected
photos reside in a different table, which would also be a little
better performing for most select queries but adds complexity to the
domain model.
You could create a database view (instead of a table) with the CREATE
VIEW statement.
def find_approved_photos
return find(:all, :conditions => ‘approved is true’)
end
and then you can reuse Model.find_approved_photos in your controllers.
Then
I remembered that rails allows you to use find_all_by_#{column_name},
which
I think might be better, and works just like find. So then:
Model.find_all_by_approved(true)
would give you all approved photos. Change to false for unapproved.
Also,
you can still pass find options like:
and so on. Also, if you want, you can omit the all in
find_all_by_approved
(ie. find_by_approved(true)) and I think it works like find(:first).
Cheers!
I realized that this is, in fact, a problem of modeling the domain:
unapproved photos aren’t photos at all in the domain sense, there is
instead
an entity called PotentialPhoto or similar. I realized this when I
noticed that,
when using a boolean “approved” field in the table, PhotosController’s
index isn’t showing the same list of photos than what is in the
database anymore
which adds unecessary complexity.
Users can upload photos (and possibly videos, music etc. in future)
each of which must be approved by an administrator before it becomes
public. The photos are being displayed in a multitude of views
(search, best photos, user profile, random photo, recently added
photos etc.) of which each (except the photo owner’s private view and
some administrative views) must only display photos that have been
approved by an administrator. That means in every of those actions, I
have to specify :conditions => ‘approved is true’ which is not DRY at
all, which is error prone etc.
I had the exact same problem, and the solution I came up with was to
override the find method in the model. For example:
Override the find method so that if pending_approval is not specified,
it defaults to false
def self.find(*args)
if args.last.is_a?(Hash) and not args.last[:conditions].blank?
if not args.last[:conditions][0].match(‘pending_approval’)
args.last[:conditions][0] = “(#{args.last[:conditions][0]}) and
pending_approval = 0”
end
end
super(*args)
end
Override the find method so that if pending_approval is not specified,
it defaults to false
def self.find(*args)
if args.last.is_a?(Hash) and not args.last[:conditions].blank?
if not args.last[:conditions][0].match(‘pending_approval’)
args.last[:conditions][0] = “(#{args.last[:conditions][0]}) and
pending_approval = 0”
end
end
super(*args)
end
Oops, never mind that code. Here’s the correct version:
def self.find(*args)
if args.last.is_a?(Hash)
if args.last[:conditions].blank?
args.last[:conditions] = ‘pending_approval = 0’
elsif not args.last[:conditions][0].match(‘pending_approval’)
args.last[:conditions][0] = “(#{args.last[:conditions][0]}) and
pending_approval = 0”
end
end
super(*args)
end
Note that the same tactic must be applied to the count method, as well.
def self.find(*args)
if args.last.is_a?(Hash)
if args.last[:conditions].blank?
args.last[:conditions] = ‘pending_approval = 0’
elsif not args.last[:conditions][0].match(‘pending_approval’)
args.last[:conditions][0] = “(#{args.last[:conditions][0]}) and
pending_approval = 0”
end
end
super(*args)
end
Hmm, still not quite right. Third time’s a charm:
def self.find(*args)
if args.last.is_a?(Hash)
if args.last[:conditions].blank?
args.last[:conditions] = ‘pending_approval = 0’
else
if args.last[:conditions].is_a?(String)
if not args.last[:conditions].match(‘pending_approval’)
args.last[:conditions] = “(#{args.last[:conditions]}) and
pending_approval = 0”
end
elsif not args.last[:conditions][0].match(‘pending_approval’)
args.last[:conditions][0] = “(#{args.last[:conditions][0]}) and
pending_approval = 0”
end
end
end
super(*args)
end
Sorry for the multiple posts, but I’m guessing this code may help
someone else one day.
Thanks for the suggestion. I tried using your code, but it gives an
error: “odd number list for Hash”
Also, I don’t think your code would work the way I need it to, anyway.
The ‘pending_approval = 0’ should be added only if the condition being
passed to find doesn’t already specify pending_approval. Otherwise, I’d
never be able to query for records that have ‘pending_approval = 1’.