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?
Regards
Linus
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/rubyonrails-talk/-/jtDjwL9A_WIJ.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.
On Tue, Jan 3, 2012 at 11:14 PM, Linus Pettersson < linus.pettersson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> 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 KarltonHTH, Peter -- Peter Vandenabeele http://twitter.com/peter_v http://rails.vandenabeele.com -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Thank you Peter. I have some follow up questions.
Let''s say I would use a scope. How could I do that? (let''s
ignore the
"image_small" for now and focus on the subcategory) There is nothing
in the
product table that I can use to select the completed products. It is only
regarded as completed if the related resellercategory is associated to a
subcategory. So, in the scope I would need to join the resellercategories
table and check if that is associated with a subcategory.
Feels a bit unnecessary to do that for a small thing as this. But maybe it
won''t affect the performance that much.
The other option I was thinking of was just to add an after_filter in
resellercategory model like this:
def update_products
self.products.each(&:save)
end
I''ll see if I can get the scope to work first.
Regards
Linus
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/rubyonrails-talk/-/kF4xK7oJ7UEJ.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.
On Tue, Jan 3, 2012 at 11:55 PM, Linus Pettersson < linus.pettersson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Thank you Peter. I have some follow up questions. > > Let''s say I would use a scope. How could I do that? (let''s ignore the > "image_small" for now and focus on the subcategory) There is nothing in the > product table that I can use to select the completed products. It is only > regarded as completed if the related resellercategory is associated to a > subcategory. So, in the scope I would need to join the resellercategories > table and check if that is associated with a subcategory. >Well, this article http://ablogaboutcode.com/2011/02/19/scopes-in-rails-3/ seems to indicate it can be done quite easily class User scope :by_age, lambda do |age| joins(:profile).where(''profile.age = ?'', age) unless age.nil? end scope :by_name, lambda{ |name| where(name: name) unless name.nil? } scope :by_email, lambda do |email| joins(:profile).where(''profile.email = ?'', email) unless email.nil? ... It joins user.profile to check on profile.age or profile.email ... I have not tested it, but seems not too difficult.> Feels a bit unnecessary to do that for a small thing as this. But maybe it > won''t affect the performance that much. >In my view, it is relevant, since it reduces the risk of cache inconsistency, which is a much harder problem to solve when your application grows. But I have had discussions with colleagues on this before and some actually preferred caching such implicit caching columns in local tables, to have simpler reporting on those tables later on (but the risk on inconsistency was always there).> > The other option I was thinking of was just to add an after_filter in > resellercategory model like this: > > def update_products > self.products.each(&:save) > end >Yes, this will work. But for any implicit caching option (also the update_all), you need to know all the models where the implicit product.complete cache is affected and have this cache update code there (currently that would only be the ResellerCategory model, but it can grow). The 3 options will work, but all have pros and cons: * Product :complete scope (no implicit caching) * Product update_all (sql level) * ResellerCategory after_save update_products (ActiveRecord level, but many queries) HTH, Peter -- Peter Vandenabeele http://twitter.com/peter_v http://rails.vandenabeele.com -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Thank you. I got the scopes working so now I can skip the extra field :) Best Regards Linus -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/_4K1YNttf5gJ. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.