What does a single splat/asterisk in a Ruby argument list mean?
It means it can have any number of arguments (including zero) and it discards all those arguments.
What does the * (asterisk) symbol do near a function argument and how to use that in others scenarios?
This is the splat operator, which comes from ruby (and is thus not rails specific). It can be applied in two ways depending on where it is used:
- to "pack" a number of arguments into an array
- to split up an array into an argument list
In your function, you see the splat operator used in the function definition. The result is that the function accepts any number of arguments. The complete argument list will be put into args
as an array.
def foo(*args)
args.each_with_index{ |arg, i| puts "#{i+1}. #{arg}" }
end
foo("a", "b", "c")
# 1. a <== this is the output
# 2. b
# 3. c
The second variant would be when you consider the following method:
def bar(a, b, c)
a + b + c
end
It requires exactly three arguments. You can now call this method like follows
my_array = [1, 2, 3]
bar(*my_array)
# returns 6
The splat applied in this case to the array will split it and pass each element of the array as an individual parameter to the method. You could do the same even by calling foo
:
foo(*my_array)
# 1. 1 <== this is the output
# 2. 2
# 3. 3
As you can see in your example method, these rules do apply to block parameters in the same way.
What does the * (star) mean in Ruby?
Variable Length Argument List, Asterisk Operator
The last parameter of a method may be preceded by an asterisk(*), which is sometimes called the 'splat' operator. This indicates that more parameters may be passed to the function. Those parameters are collected up and an array is created.
The asterisk operator may also precede an Array argument in a method call. In this case the Array will be expanded and the values passed in as if they were separated by commas.
What does the (unary) * operator do in this Ruby code?
The *
is the splat operator.
It expands an Array
into a list of arguments, in this case a list of arguments to the Hash.[]
method. (To be more precise, it expands any object that responds to to_ary
/to_a
, or to_a
in Ruby 1.9.)
To illustrate, the following two statements are equal:
method arg1, arg2, arg3
method *[arg1, arg2, arg3]
It can also be used in a different context, to catch all remaining method arguments in a method definition. In that case, it does not expand, but combine:
def method2(*args) # args will hold Array of all arguments
end
Some more detailed information here.
ruby: what does the asterisk in p *1..10 mean
It's the splat operator. You'll often see it used to split an array into parameters to a function.
def my_function(param1, param2, param3)
param1 + param2 + param3
end
my_values = [2, 3, 5]
my_function(*my_values) # returns 10
More commonly it is used to accept an arbitrary number of arguments
def my_other_function(to_add, *other_args)
other_args.map { |arg| arg + to_add }
end
my_other_function(1, 6, 7, 8) # returns [7, 8, 9]
It also works for multiple assignment (although both of these statements will work without the splat):
first, second, third = *my_values
*my_new_array = 7, 11, 13
For your example, these two would be equivalent:
p *1..10
p 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
The meaning of `*` when using as a param(not like *arg, just *)
In this specific case, save doesn't take any arguments. That's what happens with a naked splat. But, as you may be aware, calling save on an ActiveRecord
model accepts options because this method gets overridden by ActiveRecord::Validations
here:
https://github.com/rails/rails/blob/v3.1.3/activerecord/lib/active_record/validations.rb#L47
# The validation process on save can be skipped by passing <tt>:validate => false</tt>. The regular Base#save method is
# replaced with this when the validations module is mixed in, which it is by default.
def save(options={})
perform_validations(options) ? super : false
end
What does the asterisk before the variable mean in the named_scope argument list?
*items
means that the function accepts variable number of arguments. In other words, if you call it like this:
Order.by_items(item0, item1, item2)
the variable items
inside the named scope lambda function will be an array with 3 items.
To answer your real question, you should call it like this:
Order.by_items(*Item.find(:all, ...))
What does an asterisk in front of a constant mean?
I hope that it actually expanded to permit(:name, :a_field, :another_field)
:) But yeah, basically that's what it does when used on an array, it takes the values of the array and expands them out as if they were provided as individual arguments. So then you can take those array elements and send them into a method that's expecting individual arguments.
You can also use it in the inverse, you can define a method like:
def foo *args
end
...and when it's called with individual arguments:
foo 'a', 'b', 'c'
...those end up inside the foo
method in the array args
- this is very handy for wrapping another method, eg.
def some_method *args
do_something args.first
super *args # call the superclass's `some_method` with whatever args it would have received
end
Update
Btw, here's the official docs about this operator.
naked asterisk as parameter in method definition: def f(*)
def f(*)
has the same effect as def f(*args)
, except that it does not name the globbed argument array. You might use it if you want the function to accept any number of arguments but don't actually need to refer to them within the function -- for example, if you are overriding a method but calling super
without passing an explicit argument list, which results in the original arguments being passed to super
.
You can write def f(a, b, *)
as well.
Passing a hash to a function ( *args ) and its meaning
The *
is the splat (or asterisk) operator. In the context of a method, it specifies a variable length argument list. In your case, all arguments passed to func
will be putting into an array called args
. You could also specify specific arguments before a variable-length argument like so:
def func2(arg1, arg2, *other_args)
# ...
end
Let's say we call this method:
func2(1, 2, 3, 4, 5)
If you inspect arg1
, arg2
and other_args
within func2
now, you will get the following results:
def func2(arg1, arg2, *other_args)
p arg1.inspect # => 1
p arg2.inspect # => 2
p other_args.inspect # => [3, 4, 5]
end
In your case, you seem to be passing a hash as an argument to your func
, in which case, args[0]
will contain the hash, as you are observing.
Resources:
- Variable Length Argument List, Asterisk Operator
- What is the * operator doing
Update based on OP's comments
If you want to pass a Hash as an argument, you should not use the splat operator. Ruby lets you omit brackets, including those that specify a Hash (with a caveat, keep reading), in your method calls. Therefore:
my_func arg1, arg2, :html_arg => value, :html_arg2 => value2
is equivalent to
my_func(arg1, arg2, {:html_arg => value, :html_arg2 => value2})
When Ruby sees the =>
operator in your argument list, it knows to take the argument as a Hash, even without the explicit {...}
notation (note that this only applies if the hash argument is the last one!).
If you want to collect this hash, you don't have to do anything special (though you probably will want to specify an empty hash as the default value in your method definition):
def my_func(arg1, arg2, html_args = {})
# ...
end
Related Topics
Cron Is Running in Home Directory Instead of File Directory
Shortening Socket Timeout Using Timeout::Timeout(N) Does Not Seem to Work for Me
Advice on How to Validate Names and Surnames Using Regex
Nanoc Changing the Base Path When Deploying Page in Github
Ruby/Rails Array of Strings to Postgresql Insert
The Program 'Rails' Is Currently Not Installed
Ruby Is Already Using the Class Name of My Model
Rails Cancan and State MAChine - Authorizing States
Insert Rows on Specific Line in a File
Project Euler #3 in Ruby Solution Times Out
Compass Error for Command 'Grunt Server'
Scraping an Angularjs Application
Rails 4 Error with Every Command "'Load': No Implicit Conversion of Nil into String" (MAC Os X 10.9)
How Does Count Method Works in Ruby
How to Use Before :All with Capybara
Ruby How to Merge Two CSV Files with Slightly Different Headers