Reputation: 52357
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?
# ...
Upvotes: 3
Views: 2133
Reputation: 1104
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.
Upvotes: 1
Reputation: 18762
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)
Upvotes: 0
Reputation: 84114
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.
Upvotes: 3
Reputation: 52357
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.
Upvotes: 0
Reputation: 15515
Since you need a conditional assignment, I think your first version is pretty concise.
Upvotes: 1