Many times I perform logic where I look to gather an array of records, but first must check to see if any exists (so I don't get an error of a .nil array). Here is an example of some code I wrote to today, is there a 'sweeter' way to achieve the same results? If so, I would use this style of coding many times. unless project.vendors.nil? @vendors = project.vendors.find(:all) for vendor in @vendors unless vendor.products.nil? @products = vendor.products.find(:all) for product in @products unless product.prodrevs.nil? @prodrevs = product.prodrevs.find(:all) for prodrev in @prodrevs @prodrevmap << prodrev end end end end end Thanks, Kathleen
ok, I'll bite.
If the goal is get all prodrev's what's wrong with Prodrev.find(:all)?
project.vendors.find(:all).each do |vendor| vendor.products.find(:all).each do |product| product.prodrevs.find(:all).each do |prodrev| @prodrevmap << prodrev end end end
That's more compact, but why all the .find(:all) methods? You're looking for all the prodrevs under a project. If I assume:
class Project; has_many :vendors ;end class Vendor ; has_many :products ;belongs_to :project ;end class Product; has_many :prodrevs ;belongs_to :vendor ;end class Prodrev; belongs_to :product ;end
You could:
class Prodrev def self.map_for_project(project_id) find(:all, :conditions => ['projects.id = ?', project_id], :select => 'prodrevs.*', :readonly => false, :joins => ['JOIN products ON products.id = prodrevs.product_id', 'JOIN vendors ON vendors.id = products.vendor_id', 'JOIN projects ON projects.id = vendors.project_id'].join(' ')) end end
@prodrevmap = Prodrev.map_for_project(project.id)
If you do this often, you'll (most likely) benefit from letting the database do the joining for you and avoiding all the ActiveRecord objects that you'd otherwise create just to reach down to the Prodrevs.
-Rob
Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com
Marlon, Your idea looks very sexy but I suspect that it won't work if any of the finds are unsuccessful. I tried the idea (below) and it seems to look the best (so far). I'm running this routine to calculate the .xml entries for a Google Sitemap...so you should know that this is a special occurance that I'm running as a RAKE job. If anyone else is tasked with having to create a Google Sitemap on a complex database, I'd be happy to share what I have so far.
# Begin - First set of records @prodrevmap = @vendors = project.vendors.find(:all) unless project.vendors.nil? for vendor in @vendors @products = vendor.products.find(:all) unless vendor.products.nil? for product in @products @prodrevs = product.prodrevs.find(:all) unless product.prodrevs.nil? for prodrev in @prodrevs @prodrevmap << prodrev end end end # end - First set of records
Kathleen
have you seen http://github.com/queso/sitemap/tree/master?
Marlon, Your idea looks very sexy but I suspect that it won't work if any of the finds are unsuccessful. I tried the idea (below) and it seems to look the best (so far).
find :all and associations that are collections always return an
array, never nil
You might also try something like
Prodrev.find :all, :joins => {:product => {:vendor
=> :project}}, :conditions => ['projects.id = ?', project.id]
Fred
Mr. Cheung, You are truly the 'Zen Master' of Rails. Thank you for your wonderful example. Kathleen