tags:

views:

73

answers:

4

I'm sure there is a more idiomatic ruby way to write the code below:

@var = obj['blah'] unless obj['blah'].nil?

I've got a whole load of these to do (see below), and there must be a nicer way!

@num_x = obj['num_x'] unless obj['num_x'].nil?
@num_y = obj['num_y'] unless obj['num_y'].nil?
@num_iterations = obj['num_iterations'] unless obj['num_iterations'].nil?
@pe = obj['pe'] unless obj['pe'].nil?

I have a feeling that the ||= operator may be useful, but can't seem to quite work out how to use it.

+2  A: 

the shortest I can think of for this common need is

@var = obj['blah'] or @var

though if obj['blah'] can be false, you'll need to go with your original version.

The ||= operator tests the left-hand side, not the right-hand side, so doesn't apply here.

Peter
Your code it slightly different: In your example `@var` is not updated is `obj['blah'] = false`. In the OPs example it always updated except the value is `nil`.
Veger
@Veger: of course. that's why I mention that if `obj['blah']` can be false you need the original version.
Peter
@Peter: ah sorry, I did not notice it! Oh you changed the answer... :) Now you are always updating `@var` I do not know whether it is very efficient, but it is shorted code-wise...
Veger
@Veger: I changed other things, but that part was there from the beginning (and the condition still applies) :)
Peter
+3  A: 

Depending on your circumstances, and unless the instance variables already have an existing value that you want to preserve if the value in obj is nil then it might not be a problem to just let them be set to nil.

Alternatively, you could write a little helper function like:

def set_instance_variables_for_non_nil_values(h, *keys)
  keys.each do |key|
    instance_variable_set "@#{key}", h[key] unless h[key].nil?
  end
end

Then in your example code you would use it like this:

set_instance_variables_for_non_nil_values obj, 'num_x', 'num_y',
  'num_iterations', 'pe'
mikej
This is a good solution that does what the question asked. However, I would say that mass setting of instance variables like this is a bad idea unless you have a really good reason.
Squeegy
+1  A: 

Like this:

obj['blah'] && var = obj['blah']
glenn mcdonald
A: 

if @var already has a value which is not nil or false then you can use

@var &&= obj['blah']

but I would be tempted to find a simpler solution maybe merging hashes if there are lots of values.

such as:

obj = {:num_x => 23, :num_y => 75, :pe => 99}

locals = {:num_x => 1, :num_y => 2, :num_iterations => 3, :pe => 4}

puts locals.inspect #=> {:num_y=>2, :pe=>4, :num_iterations=>3, :num_x=>1}

locals.merge! obj

puts locals.inspect #=> {:num_y=>75, :pe=>99, :num_iterations=>3, :num_x=>23}

Which is used for setting options in many gems I have seen.

Joc