How are symbols used to identify arguments in ruby methods
Solution 1
Symbols and hashes are values like any other, and can be passed like any other value type.
Recall that ActiveRecord models accept a hash as an argument; it ends up being similar to this (it's not this simple, but it's the same idea in the end):
class User
attr_accessor :fname, :lname
def initialize(args)
@fname = args[:fname] if args[:fname]
@lname = args[:lname] if args[:lname]
end
end
u = User.new(:fname => 'Joe', :lname => 'Hacker')
This takes advantage of not having to put the hash in curly-brackets {}
unless you need to disambiguate parameters (and there's a block parsing issue as well when you skip the parens).
Similarly:
class TestItOut
attr_accessor :field_name, :validations
def initialize(field_name, validations)
@field_name = field_name
@validations = validations
end
def show_validations
puts "Validating field '#{field_name}' with:"
validations.each do |type, args|
puts " validator '#{type}' with args '#{args}'"
end
end
end
t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 })
t.show_validations
This outputs:
Validating field 'name' with:
validator 'presence' with args 'true'
validator 'length' with args '{min: 2, max: 10}'
From there you can start to see how things like this work.
Solution 2
I thought I'd add an update for Ruby 2+ since this is the first result I found for 'symbols as arguments'.
Since Ruby 2.0.0 you can also use symbols when defining a method. When calling the method these symbols will then act almost the same as named optional parameters in other languages. See example below:
def variable_symbol_method(arg, arg_two: "two", arg_three: "three")
[arg, arg_two, arg_three]
end
result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg"
# result is now equal to:
[:custom_symbol, "two", "Modified symbol arg"]
As shown in the example, we omit arg_two:
when calling the method and in the method body we can still access it as variable arg_two
. Also note that the variable arg_three
is indeed altered by the function call.
Solution 3
In Ruby, if you call a method with a bunch of name => value
pairs at the end of the argument list, these get automatically wrapped in a Hash
and passed to your method as the last argument:
def foo(kwargs)
p kwargs
end
>> foo(:abc=>"def", 123=>456)
{:abc=>"def", 123=>456}
>> foo("cabbage")
"cabbage"
>> foo(:fluff)
:fluff
There's nothing "special" about how you write the method, it's how you call it. It would be perfectly legal to just pass a regular Hash object as the kwargs
parameter. This syntactic shortcut is used to implement named parameters in an API.
A Ruby symbol is just a value as any other, so in your example, :first_name
is just a regular positional argument. :presence
is a symbol used as a Hash key – any type can be used as a Hash key, but symbols are a common choice because they're immutable values.
Solution 4
I think all replies have missed the point of question; and the fact it is asked by someone who is - I guess - not clear on what a symbol is ?
As a newcomer to Ruby I had similar confusions and to me an answer like following would have made more sense
Method Arguments are local variables populated by passed in values.
You cant use symbols as Arguments by themselves, as you cant change value of a symbol.
Solution 5
Symbols are not limited to hashes. They are identifiers, without the extra storage space of a string. It's just a way to say "this is ...."
A possible function definition for the validates call could be (just to simplify, I don't know off the top of my head what it really is):
def validates(column, options)
puts column.to_s
if options[:presence]
puts "Found a presence option"
end
end
Notice how the first symbol is a parameter all of its own, and the rest is the hash.
Amit Erandole
I am the content head of my very own web marketing agency, based out of Mumbai. I am a writer by profession but the dark side of my nature seems to have turned towards programming. I will have my vengeance!! I love learning javascript and ruby and amazed by the power of meta programming and shit I don't know but am very curious about.
Updated on November 11, 2020Comments
-
Amit Erandole over 3 years
I am learning rails and going back to ruby to understand how methods in rails (and ruby really work). When I see method calls like:
validates :first_name, :presence => true
I get confused. How do you write methods in ruby that accept symbols or hashes. The source code for the validates method is confusing too. Could someone please simplify this topic of using symbols as arguments in ruby class and instance methods for me?
UPDATE:
Good one @Dave! But What I was trying out was something like:
def full_name (:first_name, :last_name) @first_name = :first_name @last_name = :last_name p "#{@first_name} #{last_name}" end full_name("Breta", "Von Sustern")
Which obviously raises errors. I am trying to understand: Why is passing symbols like this as arguments wrong if symbols are just like any other value?
-
Dave Newton over 12 yearsAnd, more importantly than being immutable, they're more communicative in that they specifically act as a name or label for something.
-
Dave Newton over 12 yearsThey're still stored, it's just that each unique label is stored only once, like an interned string. OTOH, they're not eligible for GC (maybe they are in 1.9), either, so they stick around for the app's lifetime.
-
sheldonh over 12 yearsSymbols aren't GC'd in 1.9 either.
-
Dave Newton almost 12 yearsI'm not sure what you mean by "you can't use symbols as arguments by themselves", because you can...
foo(:bar)
is a perfectly legitimate function call. Perhaps I've misunderstood? -
André Barbosa about 10 yearsAlso, consider using the
fetch
method to provide defaults when getting the arguments inside a hash. -
DGM over 9 yearsRuby 2.2 now has symbol GC
-
cedricdlb over 4 yearsI think @sevgun means "You can't use symbols as parameters by themselves", where one uses the definitions "Parameters refers to the list of variables in a method declaration. Arguments are the actual values that are passed in when the method is invoked."
-
Ryan Dsouza about 3 yearsDoesn't valudations in the initialize definition have to be *validations?
-
Dave Newton about 3 years@RyanDsouza I'm not sure what you mean; do I have a typo?