idiomatic way to assign if not nil?

J

Jay Levitt

I know I can use "a ||= b" to assign b to a if a is nil.

But what about an equivalent to

a = b if b

Does that exist in a DRYer form?
 
L

Logan Capaldo

I know I can use "a ||= b" to assign b to a if a is nil.

But what about an equivalent to

a = b if b
a &&= b will almost get you there

if a is not nil or false and b is not nil or false then a = b, but if
a is nil or false and b is not nil or false then a = a. So if you can
guarantee that a will always be truthy then you can do it. I'd stick
to a = b if b for sanity's sake.
 
D

dblack

J

Jay Levitt

I have to say, when I type this:

a = b if b

I don't have the feeling that I'm repeating myself; the two b's both
pull their weight. So I wouldn't worry about it, from the DRY
perspective.

Yeah, it was more that I was doing a bunch of them at once to deal
with Rails' attr_protected feature while in a unit test, so I ended up
writing:
user.login = options[:login] if options[:login]
user.password = options[:password] if options[:password]
user.other = options[:eek:ther] if options[:eek:ther]

Felt kinda repetitive. I guess I could DRY that up in an eval loop.
 
L

Logan Capaldo

I have to say, when I type this:

a = b if b

I don't have the feeling that I'm repeating myself; the two b's both
pull their weight. So I wouldn't worry about it, from the DRY
perspective.

Yeah, it was more that I was doing a bunch of them at once to deal
with Rails' attr_protected feature while in a unit test, so I ended up
writing:
user.login = options[:login] if options[:login]
user.password = options[:password] if options[:password]
user.other = options[:eek:ther] if options[:eek:ther]

Felt kinda repetitive. I guess I could DRY that up in an eval loop.
Is this not what #attributes= is for?
user.attributes = options
 
J

Joel VanderWerf

Jay said:
user.login = options[:login] if options[:login]
user.password = options[:password] if options[:password]
user.other = options[:eek:ther] if options[:eek:ther]

Felt kinda repetitive. I guess I could DRY that up in an eval loop.

No need for eval...

[:login, :password, :eek:ther].each do |key|
user.send "#{key}=", options[key] if options.key?(key)
end
 
J

Jay Levitt

Yeah, it was more that I was doing a bunch of them at once to deal
with Rails' attr_protected feature while in a unit test, so I ended up
writing:
user.login = options[:login] if options[:login]
user.password = options[:password] if options[:password]
user.other = options[:eek:ther] if options[:eek:ther]
Felt kinda repetitive. I guess I could DRY that up in an eval loop.

Is this not what #attributes= is for?
user.attributes = options

Nope! That won't assign any attributes that are attr_protected.
 
J

Jay Levitt

Jay said:
user.login = options[:login] if options[:login]
user.password = options[:password] if options[:password]
user.other = options[:eek:ther] if options[:eek:ther]
Felt kinda repetitive. I guess I could DRY that up in an eval loop.

No need for eval...

[:login, :password, :eek:ther].each do |key|
user.send "#{key}=", options[key] if options.key?(key)
end

Perfect! In fact, I'll go even better:

User.protected_attributes.each do |key|
user.send "#{key}=", options[key] if options.key?(key)
end

Now I don't have to update my tests when I add attr_protected
attributes to my model.
 
K

Ken Bloom

a = b if b
Not really DRYer :), you just repeat a instead of b :)

But a is defintiely a variable, while b may be a function call.
In a = b if b, you compute the function twice.
In a = b or a, you compute the function only once.

--Ken
 
D

Douglas F Shearer

But a is defintiely a variable, while b may be a function call.
In a = b if b, you compute the function twice.
In a = b or a, you compute the function only once.

Took the words right out of my mouth, I must read my email more
frequently...

Douglas F Shearer
(e-mail address removed)
http://douglasfshearer.com
 
L

Logan Capaldo

But a is defintiely a variable, while b may be a function call.
In a = b if b, you compute the function twice.
In a = b or a, you compute the function only once.
Methods that are expensive and/or have side effects should probably
not be named b :)
 
A

aalfred

I know I can use "a ||= b" to assign b to a if a is nil.

But what about an equivalent to

a = b if b

Does that exist in a DRYer form?

Recently I had a similar problem. After some refactoring of code
I rewrote the code with two (non-existing, but very DRY operators)

I had those two cases:

foo = bar if !bar.nil? # (case 1) or
foo = bar if foo.nil? && !bar.nil? # (case 2)

and rewrote them into:

foo ??= bar # case 1
foo !!= bar # case 2

While this is not the same as your problem, it is quite similar.
I looks as this is not a completely isolated problem. Probably
because so many want to DRY their code. It looks like baroqueness
of code can survive only in the names of methods and variables ;-)

Alfred
 
P

Phrogz

Recently I had a similar problem. After some refactoring of code
I rewrote the code with two (non-existing, but very DRY operators)

I had those two cases:

foo = bar if !bar.nil? # (case 1) or
foo = bar if foo.nil? && !bar.nil? # (case 2)

and rewrote them into:

foo ??= bar # case 1
foo !!= bar # case 2

How did you do that, given that those operators are (as you say) non-
existing, and the code in your resulting code produces a syntax error
(under 1.8.6, anyhow)? Did you modify the Ruby source?
 
L

Logan Capaldo

How did you do that, given that those operators are (as you say) non-
existing, and the code in your resulting code produces a syntax error
(under 1.8.6, anyhow)? Did you modify the Ruby source?
I don't think he did any such thing. I think when he says he rewrote
it, he means just that, he rewrote it, not that it actually worked or
anything :)
 
E

Erik Veenstra

I've not yet seen the right answer on the original question:
"idiomatic way to assign if not nil?".

Since false isn't nil, a||=b can't a correct answer, AFAIK.

_A_ good answer could be:

a=b if a.nil?

gegroet,
Erik V. - http://www.erikveen.dds.nl/
 
K

Konrad Meyer

--nextPart1833986.QKrTjAvyWn
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

I've not yet seen the right answer on the original question:
"idiomatic way to assign if not nil?".
=20
Since false isn't nil, a||=3Db can't a correct answer, AFAIK.
=20
_A_ good answer could be:
=20
a=3Db if a.nil?
=20
gegroet,
Erik V. - http://www.erikveen.dds.nl/

=46alse isn't nil, but nil is false.

=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1833986.QKrTjAvyWn
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBG2xgmCHB0oCiR2cwRArrgAJ93pKsvxUiVmrkls6H1ZItKBxutfACgqbZZ
wfcXQvg2yAxJWrhN707GvSM=
=3Ip2
-----END PGP SIGNATURE-----

--nextPart1833986.QKrTjAvyWn--
 
A

aalfred

I don't think he did any such thing. I think when he says he rewrote
it, he means just that, he rewrote it, not that it actually worked or
anything :)

No, I did not modify ruby source (for "it is not the right thing" :).

What I did was just cleaning (DRYing) up the code. And as Logan
correctly
observed came to that 'code'. Since it cannot be done in the way I
wrote
it by adding two methods to the foo class which did the trick.

But it looks like others are bumping into similar/same repeating
patterns,
so something like that would be nice to have ;-)

Alfred
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top