DRYer way to see if array exists before I do a find?

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

On Jun 18, 2008, at 6:40 PM, Marlon M. wrote:

Many times I perform logic where I look to gather an array of
unless vendor.products.nil?
end
Thanks,
Kathleen

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 B. http://agileconsultingllc.com
[email protected]

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

On Jun 18, 2008, at 8:29 PM, [email protected] wrote:

If anyone else is tasked with having to create a Google Sitemap on a

have you seen http://github.com/queso/sitemap/tree/master?

Mr. Cheung,
You are truly the ‘Zen Master’ of Rails. Thank you for your wonderful
example.
Kathleen

On Jun 19, 4:24 am, Frederick C. [email protected]

On 19 Jun 2008, at 01:29, [email protected] wrote:

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

Frederick C. wrote:

Prodrev.find :all, :joins => {:product => {:vendor
=> :project}}, :conditions => [‘projects.id = ?’, project.id]

Fred

Hey Fred,

How’d you know I needed an example of a nested :joins statement?

:slight_smile:

Peace,
Phillip