Conditional merge with Ruby to include a parameter if it hasn't been included I have the following function, and I have a hunch it can be written more concisely in Ruby.

def template_params
  filtered_params = params[:template].permit!
  filtered_params[:published] ||= false
  filtered_params
end


The end result is that filtered_params has published: false if the params hash doesn't have published as a key.

I'm wondering if there is some kind of conditional merge w/ Ruby to turn that code into a 1-liner.

Essentially, the params hash includes "what has been changed" and when :published becomes false (it's a checkbox that gets unchecked), it naturally doesn't get included in the params hash. I wanted to pass in the fact that :published became false when it got unchecked.  

I do not need to pass in published: false by default, because whatever the default is, is fine. It is the changed state that I need, but from false to true. The alternative works: if the checkbox is checked, it becomes true and gets passed through without issue.

This is more an exercise of how can I turn this bit of code into something more "elegant" and maybe a 1-liner.  As it stands, it does exactly what I need it to do.
You want to merge params with one or more default values. How about, well, #merge?

{"published" =&gt; false}.merge(params[:template].permit!)


Only trick, if you can call it a trick, is that the default hash must use string keys, not symbols, despite the params object accepting either. The resulting hash will also be keyed with strings only.

Alternatively, you can use HashWithIndifferentAccess to get around this:

defaults = HashWithIndifferentAccess.new({ published: false })
filtered = defaults.merge(params[:template].permit!)


And filtered will be a HashWithIndifferentAccess much like params produces.

All that said, the better way to handle all this is to send the right parameters in the first place. With the code above you're always assuming that published should be set to false unless told otherwise. But there could be all sort of reasons for why only a subset of parameters are sent; if published is intentionally left out, it'll suddenly be filled in - perhaps wrongly - by the controller.

Relatedly, if the parameter is required, raise an exception if it's missing and tell the client. It's not the controller's job to fill in the blanks when faced with incomplete information. Conversely, it's the client's job to send the parameters that are necessary or required.

As I said in a comment, if you use Rails' regular checkbox helpers, they'll produce a hidden input with the checkbox's "unchecked" value, in addition to the checkbox input itself. If the checkbox is checked, it'll override the former, unchecked value. This is the typical (and better) way to solve this.

So in short, if you want to merge to hashes, use #merge. But in this case, you probably don't want to do that.