Hi!
I have an app with products, categories, subcategories and resellercategories.
Products…
belongs_to :resellercategory
has_one :subcategory, :through => :resellercategory
has_one :category, :through => :subcategory
So, there are a lot of resellercategories that are (manually) mapped to my fewer subcategories.
I have a before_save in my products model that sets if the product is complete:
def check_complete
self.complete = !image_small.blank? && !subcategory.blank?
nil
end
So, if the resellercategory that the product is related to is mapped to a subcategory, the product is marked as “complete”. However, at the moment it is only updated when the product is saved, I also want it to be updated when the resellercategory is mapped to a subcategory.
Is there any good way to do this? Should I create an after_save in my resellercategory that iterates through all the products and re-saves all of them to get the field updated?
Any easier/more effective way?
I am not sure I follow exactly, but …
Answer 1:
I assume this
" … when the resellercategory is mapped to a subcategory …"
creates (or modifies) a ResellerCategory object (and saves it
later to the database)?
So as you suggest:
“… Should I create an after_save in my resellercategory that …”
updates all associated products. Instead of
“… iterates through all the products and re-saves all of them to get the field updated? …”
you could use an update_all , but that seems quite low-level database
hacking (no models instantiated, no before/after filters …).
http://apidock.com/rails/ActiveRecord/Relation/update_all
#untested code !!
Product.where(:reseller_category_id => reseller_category.id).update_all(:complete => true)
This does not feel comfortable, but it would probably work …
Answer 2:
In reality, the Product.complete column is a de-facto cache for information
that is already present in the database. Unless your have real performance
problems associated with it, I would try to make a scope
class Product < ActiveRecord::Base
scope :complete …
that limits the products to those that are complete (that is, they have
a category and a small_image). Then Product.complete.where. …
will inlcude the correct SQL to only select the complete products,
without the implicit caching problem that you are facing now.
Very true:
There are only two hard things in Computer Science: cache
invalidation and naming things.
Phil Karlton
HTH,
Peter