You are right @chancancode . I think I have borrowed this pattern from another helper
https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/form_helper.rb#L1793
~~~ruby
      def button(value = nil, options = {}, &block)
        value, options = nil, value if value.is_a?(Hash)
        value ||= submit_default_value
        @template.button_tag(value, options, &block)
      end
~~~
It does basically the same thing. It provides all arguments to button_tag and delegate all hassling to it. I can not say is it good or bad it just produces less code and less if-else chore. I like to think of it as **Replace Conditional with Polymorphism**. As far as `content_tag` shows a polymorphic behavior it might be okish to use it. I would love to hear your thoughts on it!

According to test suite we have to make the following signatures work properly:
~~~ruby
button_tag
button_tag 'applied value'
button_tag 'applied value', name: 'action', value: 'value1'
button_tag { 'content' }
button_tag('ignored_value'){ 'content' }
button_tag(name: 'action', value: 'value1') { 'content' }
button_tag('ignored value', name: 'action', value: 'value1' ) { 'content' }
~~~
However I do not think that `content_tag` would change its behaviour, we can be more precise with an "if-else juggernaut" like this:
~~~ruby
      def button_tag(content_or_options = nil, options = nil, &block)
        opts =
            if content_or_options.is_a? Hash
              button_tag_options_with_defaults(content_or_options)
            elsif options.is_a? Hash
              button_tag_options_with_defaults(options)
            else
              button_tag_options_with_defaults({})
            end

        if block_given?
          helper.content_tag :button, opts, &block
        else
          helper.content_tag :button, content_or_options || 'Button', opts
        end
      end
~~~

Do you have any thoughts on which way is better?