views:

86

answers:

7

Is there a way to make this one liner better looking?

@var = params[:key1][:key2] unless params.blank? || params[:key1].blank?
+1  A: 

Yes, there is.

@var =  params && params[:key1] && params[:key1][:key2]
Bragboy
In your case `=` will be done in any way, but in questioner's — only when right from `unless` is equal to `false`
Nakilon
This works really well for testing for `.nil?` values but not for `.blank?`
Shadwell
good refactoring, although i think the original one is more 'readable' or understandable with one look. but nonetheless, good refactor
corroded
@Shadwell: checking if params[:key1] is blank is not neccessary, nil check is enough - we want to avoid exception here, on blank hash asking for :key2 gives nil which is ok
gertas
Anyway it works wrong. If some params lack, @var will become false, but do we need it?
Nakilon
@Nakilon : If some params lack, @var will not become false. It will be nil..
Bragboy
Anyway it deletes previous value.
Nakilon
The OP's code assigns the value of params[:key1][:key2] to @var, doesn't this code lose that?
Jeff Paquette
Wow, thanks for all the replies :-) As gertas point out that params is always present in a controller action (which is indeed where I'm working), and that nil check is enough, my original code can be reduced to @var = params[:key1][:key2] unless params[:key1].nil?
Jeppe Liisberg
+1  A: 

You can use this:

params.blank? || params[:key1].blank? || (@var = params[:key1][:key2])

But your way is more readable for me.

Nakilon
Shadwell, thanks for correct my stupid mistake )
Nakilon
A: 

Just to let you know that you can also do this, but i'm not sure it is better looking :) (and you have to be in ror):

@var = params.try(:fetch, :key1, nil).try(:fetch, :key2, nil)
hellvinz
A: 
Chris McCauley
A: 

I assume that you are using it in controller (params allways present - not nil):

@var = (params[:key1] || {})[:key2]

gertas
I'll remember this hack for codegolf...
Nakilon
actually this is not hack, it is used all around Rails and gems
gertas
A: 

This is a simple idea.

@var = params.fetch(:key1, {}).fetch(:key2, nil)

Using merge is interesting.

@var = {:key1=>{}}.merge(params)[:key1][:key2]
Shinya Miyazaki
A: 

Wow, thanks for all the replies!

I'm going to sum up the answers - as the answer seems more subtle than just another oneliner ;-)

As gertas point out that params is always present in a controller action (which is indeed where I'm working), and that nil check is enough, my original code can thus be reduced to:

@var = params[:key1][:key2] unless params[:key1].nil?

This is quite readable but not as short as other suggestions, like

params[:key1].nil? || (@var = params[:key1][:key2])

@var =  params[:key1] && params[:key1][:key2]

or even

@var = (params[:key1] || {})[:key2]

I wondered how to use rubys try() method on hashes, and hellvinz gave the answer (rewritten to match my new/realized need):

@var = params[:key1].try(:fetch, :key2, nil)

Finally, Shinya Miyazaki came up with some interesting variations using fetch and merge:

@var = params.fetch(:key1, {}).fetch(:key2, nil)

@var = {:key1=>{}}.merge(params)[:key1][:key2]

I ended up going with "my own", to honor the principle of "Clarity over Brevity" as pointed out by Chris McCauley

Thanks again everyone! :-)

Jeppe Liisberg