52

For example, I found the method name bundler? in the following snippet, and don't know whether the ? character is a specialized keyword or just part of the method name.

# This is a predicate useful for the doc:guides task of applications.
def bundler?
  # Note that rake sets the cwd to the one that contains the Rakefile
  # being executed.
  File.exists?('Gemfile')
end
Alberto Moriconi
  • 1,645
  • 10
  • 17
stanigator
  • 10,768
  • 34
  • 94
  • 129

5 Answers5

89

Method names in Ruby may contain upper-case and lower-case letters, numbers, underscores _ and the punctation signs !, ?, =.

A method name can't begin with a number, and the characters !, ? and = can only appear at the end.

Non-ASCII characters can be used in a method name, but this can lead to very confusing situations and should not be common practice.

It's good practice, while not mandatory, to start the method name with a lower-case character, because names that start with capital letters are constants in Ruby. It's still possible to use a constant name for a method, but you won't be able to invoke it without parentheses, because the interpeter will look-up for the name as a constant:

def Capital
    nil
end

Capital    # NameError: uninitialized constant Capital
Capital()  # => nil

Some very widely and consistently used conventions when defining method names are:

  1. Method names are full down-case, with underscores _ as separators for words into the name (e.g. Math::sqrt, Array#each_index, ...).

  2. Predicates have a question mark ? as last character (e.g. Array#empty?, Hash#has_key?, ...). While predicates usually return boolean values, this is not always the case: these methods just need to return nil or false if the predicate evaluates to false, any other value otherwise (e.g. File::size? returns nil if the file does not exist, the size of the file as an Integer otherwise).

  3. Methods that modify the state of the object on which they are invoked, or that have an unusual behavior have an exclamation mark ! as last character; this methods are sometimes called mutators because they usually are destructive or in-place versions of other methods (e.g. Array#sort!, Array#slice!, ...).

  4. Setters have an equal sign = as last character (e.g. Array#[]=, ...); the Ruby interpeter offers syntactic sugar for invokation of setter methods:

    a = [4, 5, 6]
    a[0] = 3    # Shorthand for a.[]=(0, 3)
    

Ruby also allows you to define operators using the operator symbol as the method name:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗
║ Operators (by precedence) ║                 Operations                  ║ Arity ║
╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣
║ ! ~ +                     ║ Boolean NOT, bitwise complement, unary plus ║     1 ║
║                           ║ (define with method name +@, Ruby 1.9+)     ║       ║
║                           ║                                             ║       ║
║ **                        ║ Exponentiation                              ║     2 ║
║                           ║                                             ║       ║
║ -                         ║ Unary minus (define with method name -@)    ║     1 ║
║                           ║                                             ║       ║
║ * / %                     ║ Multiplication, division, modulo            ║     2 ║
║                           ║                                             ║       ║
║ + -                       ║ Addition, subtraction                       ║     2 ║
║                           ║                                             ║       ║
║ << >>                     ║ Bitwise shift                               ║     2 ║
║                           ║                                             ║       ║
║ &                         ║ Bitwise AND                                 ║     2 ║
║                           ║                                             ║       ║
║ | ^                       ║ Bitwise OR, Bitwise XOR                     ║     2 ║
║                           ║                                             ║       ║
║ < <= => >                 ║ Ordering                                    ║     2 ║
║                           ║                                             ║       ║
║ == === != =~ !~ <=>       ║ Equality, pattern matching, comparison      ║     2 ║
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝

Unary operator methods are passed no arguments; binary operator methods are passed an argument, and operate on it and on self.

It's important to adhere strictly to the arity of the operators; while it is possible to define operator methods with a different arity (e.g. a + method that takes two arguments), Ruby would not allow you to call the method with operator syntax (it would however work with dot syntax).

It's good practice to adhere to the original semantics of the operators as much as possible: it should be intuitive to someone who knows the original meaning of the operator how it works with user defined classes.

The language also offers syntactic sugar for the special, non-operator ,[] method that is normally used for accessing array and hash values. The [] method can be defined with arbitrary arity.

For every binary operator in the table, except ordering, equality, comparison and pattern matching, Ruby also offers shorthand for abbreviated assignment (e.g. x += y expands to x = x + y); you can't define them as methods, but you can alter their behavior defining the operators on which they're based.

None of these characters can be used inside normal method names (e.g. do&print or start-up are not valid method names).

iconoclast
  • 21,213
  • 15
  • 102
  • 138
Alberto Moriconi
  • 1,645
  • 10
  • 17
  • 1
    Great answer! As a little note: It is customary for predicate methods (with a `?`) to return falsey (`nil` or `false`) or truethy (everything else) values, not necessary `true` and `false`. The return value is intended to be used in `if` statements where it behaves like if it were `true`and `false` but the actual return value is often not part of the intended method interface, just it's truethy or falsey property. – Holger Just May 11 '12 at 08:50
  • There's also some characters that can only be used as the entire method name, i.e. you can define methods called - + * ** / (if you're overloading those operators) but not a method called foo+bar – Frederick Cheung May 11 '12 at 16:07
  • I thought they were out of the scope of the question, but I added them for completeness. – Alberto Moriconi May 11 '12 at 22:38
  • I'm also having problems defining the method `+=` in a class. You can define `+` just fine, but not with the setter as you imply. I don't really know why and I'm not sure if it's a bug. – Andrew Oct 24 '13 at 17:34
  • You can't define the abbreviated assignment operators directly, but if you define the associated operator (e.g. `+`) it will be automatically used when you use `+=` (check the second to last paragraph in the answer). – Alberto Moriconi Oct 24 '13 at 23:32
  • This is perhaps implied in the earlier description, but not quite explicitly enough: method names ending in `=` (setters) require to be "completed" by an expression, to be valid for the parser. So methods whose names end in `=` cannot be called with multiple arguments, using the paren-comma syntax. See a more detailed explanation in the accepted answer for http://stackoverflow.com/questions/2380796/creating-a-setter-method-that-takes-extra-arguments-in-ruby – sameers Mar 19 '14 at 05:38
  • @sameers Thank you for your suggestion; while I'm not sure this level of insight on parsing is appropriate for the scope of the question, I can see that my explanation of "setters" isn't perfectly clear, and I'll make sure to edit it accordingly. – Alberto Moriconi Mar 22 '14 at 00:53
  • @AlbertoMoriconi - thanks. The point that tripped me up (I was teaching Ruby when this happened) was I'd assumed the parser behavior reflects the actual semantics, which in this case it doesn't. Even though the "setter" is a method (you can `send` it to its containing object), the existence of the `=` at the end restricts the valid succeeding token sequences. The scope of the original question is a bit vague but (like me) others might show up here because they ran into the same issue. – sameers Mar 22 '14 at 20:17
  • Can you add an explanation for why someone would choose to name a method with a capital first letter like def Cats; end? – mbigras Mar 26 '18 at 07:17
  • @mbigras, you can see some examples of such methods in the Ruby core; e.g., [Kernel#Array](https://ruby-doc.org/core-2.7.0/Kernel.html#method-i-Array) is used to convert a value to an array. So, the inferred idiomatic use-case is for conversion methods. Another example can be found in the Ruby Std-Lib, [Object#CSV](https://ruby-doc.org/stdlib-2.7.0/libdoc/csv/rdoc/Object.html#method-i-CSV). – Jordan Pickwell Feb 05 '20 at 18:33
  • Source: https://docs.ruby-lang.org/en/2.0.0/syntax/methods_rdoc.html#label-Method+Names – ddavison Mar 31 '23 at 17:34
9

What others say is true for the built-in syntax, however there seems to be no back-end restrictions on what can be used if you use methods like define_method + send:

define_method(:'$% ^&') { 0 }
define_method(:'你好') { 1 }

send(:'$% ^&') == 0 or raise
send(:'你好') == 1 or raise

This fact can be useful: for example Rails' ActiveSupport::Testing::Declarative.test method uses it so as not to do complex conversions on:

test 'Some Controller#Method' do

to a saner name, which might conflict with another test named:

test 'Some Controller_Method' do

This is mentioned on the Testing Guide.

Curiosity: a similar thing happens in Java, where the bytecode method name gives way more choice than the Java language: Why does the JVM allow us to name a function starting with a digit in bytecode?

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
4

Method names can end in !, ? or =. Underscores are allowed as well. Besides that there are several methods that look like operators (e.g. +, *, >>, []) that you can define for your own classes.

Michael Kohl
  • 66,324
  • 14
  • 138
  • 158
2

To add one thing: you can also tell an object to run a method with no name at all and it will try to invoke a method named call:

#!/usr/bin/env ruby

class Foo

=begin
  def call(*args)
    puts "received call with #{args.join(' ')}"
  end
=end

  def method_missing(m, *args, &block)
    puts "received method_missing on `#{m}(#{args.join(', ')})`"
  end

end

f = Foo.new
f.('hi')             # Not a syntax error! method_missing with m of :call
f.send :'', 'hmm'    # method_missing with m set to :''
f.send nil, 'bye'    # raises an error

There is not actually any method named call defined on Object, but there is one on the Method and Proc classes.

In some languages () is an operator for function invocation, and that seems pretty similar to what's happening here.

This is used e.g. in Rails' JBuilder:

https://github.com/rails/jbuilder

It is documented on page 196 of the O'Reilly Ruby book:

Ruby 1.9 offers an additional way to invoke a Proc object; as an alternative to square brackets, you can use parentheses prefixed with a period:

z = f.(x,y)

.() looks like a method invocation missing the method name. This is not an operator that can be defined, but rather is syntactic-sugar that invokes the call method. It can be used with any object that defines a call method and is not limited to Proc objects.

Paul A Jungwirth
  • 23,504
  • 14
  • 74
  • 93
1

The characters allowed are: a-Z,, 0-9 as long as not at the beginning, _, and ? (for boolean functions) and ! (for destructive functions) and = (for setters).

Linuxios
  • 34,849
  • 13
  • 91
  • 116