Assignment operator that treats empty and nil as the same thing

test1

otest = {};
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

test2

otest = {‘first_name’=>’’};
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

Problem: test1 produces the correct output, but test2 produces
unwanted output (the value remains as an empty string). I realize that
ruby treats the empty string as “true” … nevertheless I want to find
an assignment operator in ruby that treats nil and empty exactly the
same way, with the behavior shown in test1.

Question: Is there a way to do this in ruby without resorting to an
if statement or some other construct such as:

otest[‘first_name’] = (otest[‘first_name’].empty?) ‘homer’ :
otest[‘first_name’];

I would like to handle this with a single assignment operator, just
like you can do in test1.

[email protected] wrote:

I would like to handle this with a single assignment operator, just
like you can do in test1.

There is no such operator in Ruby. You have to make an if statement or
something. Also remember that if the value is nil, calling empty? on it
raises an error, so you have to check first for nil? and then for
empty?.

You can make it a bit easier with something like this:

class Object
def nothing?
if nil?
true
elsif respond_to? :empty? and empty?
true
elsif respond_to? :zero? and zero?
true
else
false
end
end
end

You won’t have to check both conditions now.

TPR.

[email protected] [email protected] wrote:

Problem: test1 produces the correct output, but test2 produces

I would like to handle this with a single assignment operator, just
like you can do in test1.

Would it suffice to subvert Hash in such a way that the value of an
element whose value is the empty string is reported as nil?

class Hash
alias_method “origfetch”, “[]”
def
result = origfetch(what)
if result == ‘’
nil
else
result
end
end
end

h = {“hey”=>"", “ho”=>“ha”}
h[“hey”] ||= “homer”
p h

If that’s too strong, you can devise your own function:

class Hash
def set_if_empty(k,v)
cur = self[k]
if cur.nil? || cur == ‘’
self[k] = v
end
end
end

h = {“hey”=>"", “ho”=>“ha”}
h.set_if_empty(“hey”, “homer”)
p h

On Aug 29, 6:01 pm, “[email protected][email protected]
wrote:

Problem: test1 produces the correct output, but test2 produces

I would like to handle this with a single assignment operator, just
like you can do in test1.

The problem is that you think that otest['first_name] is nil in both
tests when you try the conditional assignment. As the following code
shows it’s only nil the first time; the second time it’s (an empty)
String.

otest = {};
puts otest[‘first_name’] .class.to_s
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

test2

otest = {‘first_name’=>’’};
puts otest[‘first_name’] .class.to_s
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

HTH,
Richard

On Aug 29, 10:21 pm, RichardOnRails
[email protected] wrote:

test2

Question: Is there a way to do this in ruby without resorting to an
shows it’s only nil the first time; the second time it’s (an empty)
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

HTH,
Richard

Woops. I only glanced at your post when I responded. I only
belatedly noticed that you understood the nil and and an empty string
were involved. My apologies.

On Aug 29, 10:21 pm, RichardOnRails
[email protected] wrote:

test2

Question: Is there a way to do this in ruby without resorting to an
shows it’s only nil the first time; the second time it’s (an empty)
otest[‘first_name’] ||= ‘homer’;
puts otest.inspect;

HTH,
Richard

Maybe I can redeem myself: Matt gave you a great solution in reopening
the Hash definition. I recommend a minor improvement as follows:

class Hash
alias_method “orig_fetch”, “[]”
def
result = orig_fetch(what)
result = nil if result == ‘’
end
end

test1

otest = {}
otest[‘first_name’] ||= ‘homer’
puts otest.inspect #= {“first_name”=>“homer”}

test2

otest = {‘first_name’=>’’}
otest[‘first_name’] ||= ‘homer’
puts otest.inspect #= {“first_name”=>“homer”}

HTH,
Richard

Xavier N. wrote:

On Sat, Aug 30, 2008 at 5:00 AM, RichardOnRails
[email protected]lid wrote:

Maybe I can redeem myself: Matt gave you a great solution in reopening
the Hash definition. I recommend a minor improvement as follows:

class Hash
alias_method “orig_fetch”, “[]”
def
result = orig_fetch(what)
result = nil if result == ‘’
end
end

In my view that’s abusing open classes. Ruby has well-defined boolean
semantics, and Hash#[] is a fundamental method. People have
expectations about those ones.

I agree with that. But if it’s just one hash object that causes you
problems, you can always change the method in the object’s eigenclass:

class << your_hash_object
alias_method “origfetch”, “[]”
def
result = origfetch(what)
if result == ‘’
nil
else
result
end
end
end

This way you won’t break the existing functionality for other hashes.

Or you could simply extend the class, modify the method in the
descendant class, and make all your hashes instances of the descendant
class.

TPR.

On Sat, Aug 30, 2008 at 5:00 AM, RichardOnRails
[email protected] wrote:

Maybe I can redeem myself: Matt gave you a great solution in reopening
the Hash definition. I recommend a minor improvement as follows:

class Hash
alias_method “orig_fetch”, “[]”
def
result = orig_fetch(what)
result = nil if result == ‘’
end
end

In my view that’s abusing open classes. Ruby has well-defined boolean
semantics, and Hash#[] is a fundamental method. People have
expectations about those ones.

In this case I think it could be better just to program explicitly
your particular logic, either by hand, or in an clear separate method
set_if_blank(key, value). I believe that one may be added to Hash if
it deserves it in your app.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs