3
conditions[:foo] = params[:foo] if params[:foo].present? 

It will only create a key-value pair in the conditions hash if the key-value pair is present in params.

Is there a way to write it shorter? I was thinking about Hash#fetch:

conditions[:foo] = params.fetch(:foo, nil) 

But it is not what I want, because then I'll get a pair with nil value, if there is no such key in params.

I only need the conditions key-value created if such a key-value is present in params.

I am asking the question because I have a few similar lines of assigning, where params[:foo] is repeated twice on each line:

 conditions[:foo] = params[:foo] if params[:foo].present? conditions[:bar] = params[:bar] if params[:bar].present? conditions[:baz] = params[:baz] if params[:baz].present? conditions[:zxc] = params[:zxc] if params[:zxc].present? # ... 
3
  • Suppose your params is params = {foo: "foo", bar: "bar"} then which keys and values you wanted to store in conditions ?. Commented Jan 15, 2016 at 8:22
  • If the whole point is not to repeat params[:foo], you can do it with select and merge!, but it's uglier and slower. Commented Jan 15, 2016 at 8:26
  • @ndn yea, I am having few similar lines, and seeing these repeated twice on each line params[:foo] irritates me :) Commented Jan 15, 2016 at 8:29

5 Answers 5

3

First off, in your original code I would use params.key? (unless you really don't care about cases where the value is false, empty array etc). I would probably stick with that since it is very clear and not that verbose.

One alternative I can think of:

conditions.merge!(params.slice(:foo)) 

This requires active support, and would stay concise even if you did this with many hash keys - you would just add them to the call to slice.

slice uses has_key? to return only the desired portion of the hash so handles values like false and [] as I suggest rather than as your question implements them.

Sign up to request clarification or add additional context in comments.

5 Comments

thanks a lot! Good point with has_key! (Rubocop says, that has_key is deprecated in favor of key)
Slice will get {foo: nil} if :foo was not present in params hash - it is not equivalent to checking present? OP does not want foo: "" either - so calling compact on slice output won't solve the problem either.
It is indeed not equivalent to calling present? - I explicitly noted that
explicitly noted that - where?
@FrederickCheung :-) I don't see use of word "present" present in that last sentence of the "answer", unless I am missing something.
1

Since you need a conditional assignment, I think your first version is pretty concise.

Comments

1

I think the only problem with your code is the repetition. Perhaps this is a bit contentious, but I would DRY it up with a lambda.

lAdd ->(k) { conditions[k] = params[k] if params[k].present? } lAdd.(:foo) lAdd.(:bar) lAdd.(:baz) lAdd.(:zxc) 

Of course if you find yourself doing this in multiple places, it should be a common helper function, rather than a lambda that hardcodes the two hashes.

1 Comment

Ruby variables are typically lower-snake-case (l_add) rather than camelCase as shown here, but this is otherwise a good solution.
0

I asked the question because I had few similar lines of assigning, where params[:foo] is repeated twice on each line:

 conditions[:foo] = params[:foo] if params[:foo].present? conditions[:bar] = params[:bar] if params[:bar].present? conditions[:baz] = params[:baz] if params[:baz].present? conditions[:zxc] = params[:zxc] if params[:zxc].present? # ... 

What I came up to shorten what I had is the following:

 %i(foo baz bar zxc).each do |value| conditions[value] = params[value] if params[value].present? end 

But I thought it is much less readable and wanted to stick with a new line for each key-value assignment, but in shorter form.

2 Comments

You could create a method that would be invoked doit(conditions, params, :foo, bar, haz, zxc). Incidentally, when you need four metasyntactic variables, qux (or quux) seems to be the #4 of choice. I've never seen zxc, but it does seem to work.
@CarySwoveland I used zxc cause qux flew out of my head at the moment of writing :) Didn't know it is called metasyntactic variables, thanks!
0

Here is one alternate way to do this:

require "active_support/all" params = {foo: "", bar: "value", baz: nil, zxc: false} conditions = {} keys = %i(foo bar baz zxc) present_params = params.slice(*keys).select{|_,v| v.present? } conditions.merge!(present_params) 

2 Comments

Although this is both longer and more complicated to read than what the OP started out with
@WandMaker my bad regarding the additional context.. Edited the question

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.