lib/roda.rb
def define_roda_method(meth, expected_arity, &block)
          if meth.is_a?(String)
            meth = roda_method_name(meth)
          end
          call_meth = meth

          if (check_arity = opts.fetch(:check_arity, true)) && !block.lambda?
            required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(block)

            if keyword == :required && (expected_arity == 0 || expected_arity == 1)
              raise RodaError, "cannot use block with required keyword arguments when calling define_roda_method with expected arity #{expected_arity}"
            end

            case expected_arity
            when 0
              unless required_args == 0
                if check_arity == :warn
                  RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 0, but arguments required for #{block.inspect}"
                end
                b = block
                block = lambda{instance_exec(&b)} # Fallback
              end
            when 1
              if required_args == 0 && optional_args == 0 && !rest
                if check_arity == :warn
                  RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but no arguments accepted for #{block.inspect}"
                end
                temp_method = roda_method_name("temp")
                class_eval("def #{temp_method}(_) #{meth =~ /\A\w+\z/ ? "#{meth}_arity" : "send(:\"#{meth}_arity\")"} end", __FILE__, __LINE__)
                alias_method meth, temp_method
                undef_method temp_method
                private meth
                alias_method meth, meth
                meth = :"#{meth}_arity"
              elsif required_args > 1
                b = block
                block = lambda{|r| instance_exec(r, &b)} # Fallback
              end
            when :any
              if check_dynamic_arity = opts.fetch(:check_dynamic_arity, check_arity)
                if keyword
                  # Complexity of handling keyword arguments using define_method is too high,
                  # Fallback to instance_exec in this case.
                  b = block
                  block = if RUBY_VERSION >= '2.7'
                    eval('lambda{|*a, **kw| instance_exec(*a, **kw, &b)}', nil, __FILE__, __LINE__) # Keyword arguments fallback
                  else
                    # :nocov:
                    lambda{|*a| instance_exec(*a, &b)} # Keyword arguments fallback
                    # :nocov:
                  end
                else
                  arity_meth = meth
                  meth = :"#{meth}_arity"
                end
              end
            else
              raise RodaError, "unexpected arity passed to define_roda_method: #{expected_arity.inspect}"
            end
          end

          define_method(meth, &block)
          private meth
          alias_method meth, meth

          if arity_meth
            required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(instance_method(meth))
            max_args = required_args + optional_args
            define_method(arity_meth) do |*a|
              arity = a.length
              if arity > required_args
                if arity > max_args && !rest
                  if check_dynamic_arity == :warn
                    RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. At most #{max_args} arguments accepted, but #{arity} arguments given for #{block.inspect}"
                  end
                  a = a.slice(0, max_args)
                end
              elsif arity < required_args
                if check_dynamic_arity == :warn
                  RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. #{required_args} args required, but #{arity} arguments given for #{block.inspect}"
                end
                a.concat([nil] * (required_args - arity))
              end

              send(meth, *a)
            end
            private arity_meth
            alias_method arity_meth, arity_meth
          end

          call_meth
        end
# Define an instance method using the block with the provided name and
# expected arity.  If the name is given as a Symbol, it is used directly.
# If the name is given as a String, a unique name will be generated using
# that string.  The expected arity should be either 0 (no arguments),
# 1 (single argument), or :any (any number of arguments).
#
# If the :check_arity app option is not set to false, Roda will check that
# the arity of the block matches the expected arity, and compensate for
# cases where it does not.  If it is set to :warn, Roda will warn in the
# cases where the arity does not match what is expected.
#
# If the expected arity is :any, Roda must perform a dynamic arity check
# when the method is called, which can hurt performance even in the case
# where the arity matches.  The :check_dynamic_arity app option can be
# set to false to turn off the dynamic arity checks.  The
# :check_dynamic_arity app option can be to :warn to warn if Roda needs
# to adjust arity dynamically.
#
# Roda only checks arity for regular blocks, not lambda blocks, as the
# fixes Roda uses for regular blocks would not work for lambda blocks.
#
# Roda does not support blocks with required keyword arguments if the
# expected arity is 0 or 1.
Define an instance method using the block with the provided name and
expected arity.  If the name is given as a Symbol, it is used directly.
If the name is given as a String, a unique name will be generated using
that string.  The expected arity should be either 0 (no arguments),
1 (single argument), or :any (any number of arguments).

If the :check_arity app option is not set to false, Roda will check that
the arity of the block matches the expected arity, and compensate for
cases where it does not.  If it is set to :warn, Roda will warn in the
cases where the arity does not match what is expected.

If the expected arity is :any, Roda must perform a dynamic arity check
when the method is called, which can hurt performance even in the case
where the arity matches.  The :check_dynamic_arity app option can be
set to false to turn off the dynamic arity checks.  The
:check_dynamic_arity app option can be to :warn to warn if Roda needs
to adjust arity dynamically.

Roda only checks arity for regular blocks, not lambda blocks, as the
fixes Roda uses for regular blocks would not work for lambda blocks.

Roda does not support blocks with required keyword arguments if the
expected arity is 0 or 1.
Define an instance method using the block with the provided name and expected arity . If the name is given as a Symbol it is used directly . If the name is given as a String a unique name will be generated using that string . The expected arity should be either 0 ( no arguments ) 1 ( single argument ) or : any ( any number of arguments ) . If the : check_arity app option is not set to false Roda will check that the arity of the block matches the expected arity and compensate for cases where it does not . If it is set to : warn Roda will warn in the cases where the arity does not match what is expected . If the expected arity is : any Roda must perform a dynamic arity check when the method is called which can hurt performance even in the case where the arity matches . The : check_dynamic_arity app option can be set to false to turn off the dynamic arity checks . The : check_dynamic_arity app option can be to : warn to warn if Roda needs to adjust arity dynamically . Roda only checks arity for regular blocks not lambda blocks as the fixes Roda uses for regular blocks would not work for lambda blocks . Roda does not support blocks with required keyword arguments if the expected arity is 0 or 1 .
def define_roda_method(meth, expected_arity, &block)
          if meth.is_a?(String)
            meth = roda_method_name(meth)
          end
          call_meth = meth
          if (check_arity = opts.fetch(:check_arity, true)) && !block.lambda?
            required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(block)
            if keyword == :required && (expected_arity == 0 || expected_arity == 1)
              raise RodaError, "cannot use block with required keyword arguments when calling define_roda_method with expected arity #{expected_arity}"
            end
            case expected_arity
            when 0
              unless required_args == 0
                if check_arity == :warn
                  RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 0, but arguments required for #{block.inspect}"
                end
                b = block
                block = lambda{instance_exec(&b)} 
              end
            when 1
              if required_args == 0 && optional_args == 0 && !rest
                if check_arity == :warn
                  RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but no arguments accepted for #{block.inspect}"
                end
                temp_method = roda_method_name("temp")
                class_eval("def #{temp_method}(_) #{meth =~ /\A\w+\z/ ? "#{meth}_arity" : "send(:\"#{meth}_arity\")"} end", __FILE__, __LINE__)
                alias_method meth, temp_method
                undef_method temp_method
                private meth
                alias_method meth, meth
                meth = :"#{meth}_arity"
              elsif required_args > 1
                b = block
                block = lambda{|r| instance_exec(r, &b)} 
              end
            when :any
              if check_dynamic_arity = opts.fetch(:check_dynamic_arity, check_arity)
                if keyword
                   to instance_exec in this case.
                  b = block
                  block = if RUBY_VERSION >= '2.7'
                    eval('lambda{|*a, **kw| instance_exec(*a, **kw, &b)}', nil, __FILE__, __LINE__) 
                  else
                    lambda{|*a| instance_exec(*a, &b)} 
                  end
                else
                  arity_meth = meth
                  meth = :"#{meth}_arity"
                end
              end
            else
              raise RodaError, "unexpected arity passed to define_roda_method: #{expected_arity.inspect}"
            end
          end
          define_method(meth, &block)
          private meth
          alias_method meth, meth
          if arity_meth
            required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(instance_method(meth))
            max_args = required_args + optional_args
            define_method(arity_meth) do |*a|
              arity = a.length
              if arity > required_args
                if arity > max_args && !rest
                  if check_dynamic_arity == :warn
                    RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. At most #{max_args} arguments accepted, but #{arity} arguments given for #{block.inspect}"
                  end
                  a = a.slice(0, max_args)
                end
              elsif arity < required_args
                if check_dynamic_arity == :warn
                  RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. #{required_args} args required, but #{arity} arguments given for #{block.inspect}"
                end
                a.concat([nil] * (required_args - arity))
              end
              send(meth, *a)
            end
            private arity_meth
            alias_method arity_meth, arity_meth
          end
          call_meth
        end
def define_roda_method ( meth , expected_arity , & block ) if meth . is_a? ( String ) meth = roda_method_name ( meth ) end call_meth = meth if ( check_arity = opts . fetch ( :check_arity , true ) ) && ! block . lambda? required_args , optional_args , rest , keyword = _define_roda_method_arg_numbers ( block ) if keyword == :required && ( expected_arity == 0 || expected_arity == 1 ) raise RodaError , "cannot use block with required keyword arguments when calling define_roda_method with expected arity #{expected_arity}" end case expected_arity when 0 unless required_args == 0 if check_arity == :warn RodaPlugins . warn "Arity mismatch in block passed to define_roda_method. Expected Arity 0, but arguments required for #{block.inspect}" end b = block block = lambda { instance_exec ( & b ) } end when 1 if required_args == 0 && optional_args == 0 && ! rest if check_arity == :warn RodaPlugins . warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but no arguments accepted for #{block.inspect}" end temp_method = roda_method_name ( "temp" ) class_eval ( "def #{temp_method}(_) #{meth =~ /\A\w+\z/ ? "#{meth}_arity" : "send(:\"#{meth}_arity\")"} end" , __FILE__ , __LINE__ ) alias_method meth , temp_method undef_method temp_method private meth alias_method meth , meth meth = :" #{ meth } _arity " elsif required_args > 1 b = block block = lambda { | r | instance_exec ( r , & b ) } end when :any if check_dynamic_arity = opts . fetch ( :check_dynamic_arity , check_arity ) if keyword b = block block = if RUBY_VERSION >= '2.7' eval ( 'lambda{|*a, **kw| instance_exec(*a, **kw, &b)}' , nil , __FILE__ , __LINE__ ) else lambda { | * a | instance_exec ( * a , & b ) } end else arity_meth = meth meth = :" #{ meth } _arity " end end else raise RodaError , "unexpected arity passed to define_roda_method: #{expected_arity.inspect}" end end define_method ( meth , & block ) private meth alias_method meth , meth if arity_meth required_args , optional_args , rest , keyword = _define_roda_method_arg_numbers ( instance_method ( meth ) ) max_args = required_args + optional_args define_method ( arity_meth ) do | * a | arity = a . length if arity > required_args if arity > max_args && ! rest if check_dynamic_arity == :warn RodaPlugins . warn "Dynamic arity mismatch in block passed to define_roda_method. At most #{max_args} arguments accepted, but #{arity} arguments given for #{block.inspect}" end a = a . slice ( 0 , max_args ) end elsif arity < required_args if check_dynamic_arity == :warn RodaPlugins . warn "Dynamic arity mismatch in block passed to define_roda_method. #{required_args} args required, but #{arity} arguments given for #{block.inspect}" end a . concat ( [ nil ] * ( required_args - arity ) ) end send ( meth , * a ) end private arity_meth alias_method arity_meth , arity_meth end call_meth end
Define an instance method using the block with the provided name and
expected arity.
Define an instance method using the block with the provided name and expected arity .
# Fallback # Fallback # Complexity of handling keyword arguments using define_method is too high, # Fallback to instance_exec in this case. # Keyword arguments fallback # :nocov: # Keyword arguments fallback # :nocov:
meth
expected_arity
block