How to Pass Multiple Arguments to a Ruby Method as an Array

How do I pass multiple arguments to a ruby method as an array?

Ruby handles multiple arguments well.

Here is a pretty good example.

def table_for(collection, *args)
p collection: collection, args: args
end

table_for("one")
#=> {:collection=>"one", :args=>[]}

table_for("one", "two")
#=> {:collection=>"one", :args=>["two"]}

table_for "one", "two", "three"
#=> {:collection=>"one", :args=>["two", "three"]}

table_for("one", "two", "three")
#=> {:collection=>"one", :args=>["two", "three"]}

table_for("one", ["two", "three"])
#=> {:collection=>"one", :args=>[["two", "three"]]}

(Output cut and pasted from irb)

How to pass multiple arguments into a Ruby method

It's the space before the parens. Remove it. Instead of treating array_1 and array_2 as args, it's treating it as a parenthesized expression (with the whole expression being one arg) and complaining about the comma. Your code should look like

parser(array_1, array_2)

Incidentally, Ruby 1.8.7 seems to simply emit a warning about this before behaving correctly.

Passing multiple arguments to variable argument ruby method using array

You can use the splat both at method definition and method invocation. This should work:

column_widths(*array_of_widths)

How to pass multiple arguments in Ruby?

You should use parenthesis :

(@cart.name_for_line_item(line_item).should).include? puppy_name 

Latest version of rspec allow another syntax :

expect(@cart.name_for_line_item(line_item)).to include(puppy_name)

Link to rspec documentation : https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

Ruby: What is the best way to interact with a method that accepts multiple arguments?

As far as I've understood, you do not want to provide a hash as an argument, but rather an array of values, skipping key names.

If you are using a third party library, and that method is defined there - it is not possible because that method was designed to receive an argument in a specified form (in your example hash must have some specific keys), and Ruby does not provide any capability to know what user had in mind (If you want to go extreme you can write of course a source file parser that would extract an arguments that come from that hash).

If you are designing method by your own, you can just:

def initialize(arguments = {}) 
case arguments
when Hash
@foo = arguments[:foo]
@bar = arguments[:bar]
when Array
@foo = arguments[0]
@foo = arguments[1]
else
raise ArgumentError.new("argument of type Hash or Array expected")
end
end

Ruby block taking array or multiple parameters

Ruby's block mechanics have a quirk to them, that is if you're iterating over something that contains arrays you can expand them out into different variables:

[ %w[ a b ], %w[ c d ] ].each do |a, b|
puts 'a=%s b=%s' % [ a, b ]
end

This pattern is very useful when using Hash#each and you want to break out the key and value parts of the pair: each { |k,v| ... } is very common in Ruby code.

If your block takes more than one argument and the element being iterated is an array then it switches how the arguments are interpreted. You can always force-expand:

[ %w[ a b ], %w[ c d ] ].each do |(a, b)|
puts 'a=%s b=%s' % [ a, b ]
end

That's useful for cases where things are more complex:

[ %w[ a b ], %w[ c d ] ].each_with_index do |(a, b), i|
puts 'a=%s b=%s @ %d' % [ a, b, i ]
end

Since in this case it's iterating over an array and another element that's tacked on, so each item is actually a tuple of the form %w[ a b ], 0 internally, which will be converted to an array if your block only accepts one argument.

This is much the same principle you can use when defining variables:

a, b = %w[ a b ]
a
# => 'a'
b
# => 'b'

That actually assigns independent values to a and b. Contrast with:

a, b = [ %w[ a b ] ]
a
# => [ 'a', 'b' ]
b
# => nil

Passing multiple arguments to send

Ruby has a splat operator, the unary prefix * operator that can be used in two places with dual meanings:

  • in a parameter list in a method, block, or lambda definition, it means "package all remaining arguments into an Array and bind it to this parameter"
  • in an argument list of a message send or a yield as well as the left-hand side of an assignment expression, it means "explode this Array into its individual elements as if they had been written individually in its place"

So, for example:

foo(*some_array)

is equivalent to

foo(some_array[0], some_array[1], some_array[2], …, some_array[some_array.size])

So, in your case, all you need to do is

send(*ARGV)

Note, that this obviously allows anyone who can manipulate ARGV to execute any arbitrary Ruby code, including but not limited to, erasing the hard disk, or launching the proverbial nuclear missiles. But, your original code has that same flaw. You really should perform validation here, but that is orthogonal to your question.

Can you supply arguments to the map(&:method) syntax in Ruby?

You can create a simple patch on Symbol like this:

class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

Which will enable you to do not only this:

a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]

But also a lot of other cool stuff, like passing multiple parameters:

arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]

And even work with inject, which passes two arguments to the block:

%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"

Or something super cool as passing [shorthand] blocks to the shorthand block:

[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Here is a conversation I had with @ArupRakshit explaining it further:

Can you supply arguments to the map(&:method) syntax in Ruby?


As @amcaplan suggested in the comment below, you could create a shorter syntax, if you rename the with method to call. In this case, ruby has a built in shortcut for this special method .().

So you could use the above like this:

class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Here is a version using Refinements (which is less hacky than globally monkey patching Symbol):

module AmpWithArguments

refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

end

using AmpWithArguments

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Ruby passing multiple parameters in methods

You need to do this:

def ss(a,method="GET", *b)
puts a
end

When splat operators are used to accept multiple inputs, it should always be the last parameter of a method. Also a method can have only one splat parameter.

Thanks Cary for a clear and crisp explanation over how to use splats:

Basically, the rule is that if it's unambiguous, it's OK--Ruby will
figure it out. If, however, you add a variable with a default value to
my example (def test(*a,b); p a; p b; end; test 1,2,3), it becomes ambiguous, so Ruby will complain.



Related Topics



Leave a reply



Submit