Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would you express an idiom "with this object, if it exists, do this" in Ruby?

Tags:

ruby

Very often in Ruby (and Rails specifically) you have to check if something exists and then perform an action on it, for example:

if @objects.any?
  puts "We have these objects:"
  @objects.each { |o| puts "hello: #{o}"
end

This is as short as it gets and all is good, but what if you have @objects.some_association.something.hit_database.process instead of @objects? I would have to repeat it second time inside the if expression and what if I don't know the implementation details and the method calls are expensive?

The obvious choice is to create a variable and then test it and then process it, but then you have to come up with a variable name (ugh) and it will also hang around in memory until the end of the scope.

Why not something like this:

@objects.some_association.something.hit_database.process.with :any? do |objects|
    puts "We have these objects:"
    objects.each { ... }
end

How would you do this?

like image 700
Gunchars Avatar asked Dec 11 '12 21:12

Gunchars


2 Answers

Note that there's no reason to check that an array has at least one element with any? if you're only going to send each, because sending each to an empty array is a no-op.

To answer your question, perhaps you are looking for https://github.com/raganwald/andand?

like image 172
hdgarrood Avatar answered Nov 15 '22 04:11

hdgarrood


Indeed, using a variable pollutes the namespace, but still, I think if (var = value).predicate is is a pretty common idiom and usually is perfectly ok:

if (objects = @objects.some_association.hit_database).present?
  puts "We have these objects: #{objects}"
end

Option 2: if you like to create your own abstractions in a declarative fashion, that's also possible using a block:

@objects.some_association.hit_database.as(:if => :present?) do |objects|
  puts "We have these objects: #{objects}"
end

Writing Object#as(options = {}) is pretty straigthforward.

like image 43
tokland Avatar answered Nov 15 '22 05:11

tokland