What Are the Uppercase and Lowercase Rules of Ruby Method Name

What are the uppercase and lowercase rules of ruby method name?

By convention, things that start with uppercase letters are constants. When you invoke SayHi, you're telling Ruby to look for a constant with this name. Of course, there isn't one, so it fails.

If you want to invoke the method, you'll need to add a pair of parentheses. For example,

def S
puts "shazam!"
end

S #=> NameError: uninitialized constant S
S() #=> "shazam!"

Inside of a class, the resolution rules are a little different. Let's define a simple class with a constant and a method named to look like a constant:

irb(main):001:0> class C
irb(main):002:1> A = "x"
irb(main):003:1> def B
irb(main):004:2> puts "B() invoked"
irb(main):005:2> end
irb(main):006:1> end
=> nil

Now, A is certainly a constant. But what about B?

irb(main):008:0> C.const_defined?("A")
=> true # A is a constant!
irb(main):009:0> C.const_defined?("B")
=> false # B looks like a constant but isn't, because we
# used "def" to create it. "def" is for methods,
# not constants.

So it isn't a constant, just a method with that name. When we try to access B from an instance of C, now Ruby's looking for a method:

irb(main):011:0> C.new.B
B() invoked
=> nil

If we wanted to access a constant of C instead, we use the scope qualifier :::

irb(main):012:0> C::A
=> "x"

What are the restrictions for method names in Ruby?

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 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).

Ruby treats method with uppercase name differently

Why doesn't Ruby find the Uppercase method?

Because it thinks it's a constant. :: is the constant resolution operator. The fact that it also works for message sends is not really useful outside of obfuscated programming contests.

If you want to treat it as a message send, you have to make clear to Ruby that you mean a message send, by either passing an empty argument list or using standard message sending syntax:

Foo::Uppercase()
Foo.Uppercase

How else would you be able to access a constant named Uppercase namespaced within Foo?

Note that this is similar to local variables:

def foo; 'method' end

foo #=> 'method'

foo = 'variable'

foo #=> 'variable'

foo() #=> 'method'

self.foo #=> 'method'

What is the real reason for Ruby class names being capitalised?

As you said, the name of a class is that of the first constant it has been assigned to. You can only use constants with the class keyword because it has been decided that the class keyword should only be used to create named classes.

The rationale probably being that allowing local variables would confuse uses, who would use class lowercase_class_name, not knowing the difference between lower case and upper case identifiers and then wonder why the classname was not visible everywhere (i.e. why def foo() lowercase_class_name.new end did not work).

By making the default way to create classes specific to constants, classes defined this way will be visible everywhere and there is at least a suggestion that the value associated with that name should not change (i.e. you get a warning otherwise).

People who know what they're doing can still do local_variable = Class.new { ... } if they need to.

Capitalize a final first and last name in my program

Have a look at this: https://ruby-doc.org/core-2.2.0/String.html#method-i-capitalize-21

You could do this before you print the secret name:

output = output.split.each { |name| name.capitalize! }.join(' ')

and the same for the original name:

original_name = original_name.split.each { |name| name.capitalize! }.join(' ')

Examples from Ruby docs:

a = "hello"
a.capitalize! #=> "Hello"
a #=> "Hello"
a.capitalize! #=> nil

Or use Rails' titleize method if you are using Rails.

http://apidock.com/rails/String/titleize

Why is __FILE__ uppercase and __dir__ lowercase?

I think that is because __FILE__ is a parse-time constant whereas __dir__ is a function and returns File.dirname(File.realpath(__FILE__))

For more details, see This discussion

Rails Capitalization/Pluralization Rules

Most of the time, you will need to access different models across the app. And you would always access them with singular name with first letter uppercase'd like User, Tweet. Regarding controllers, I don't think so you would ever to access a controller from some other controller.

Remember, if are using raw SQL, and you want to access the table of a model, that would always be in plural and all lower case, like users for User, and tweets for Tweet.

Regarding routes, they are always accessed through lowercase words, and deciding whether singular or plural -- it depends upon the context.

If you are accessing all tweets, the route method will be tweets_path, and if want one tweet, then tweet_path(1) or edit_tweet_path(1) where 1 being the id of the tweet that you want to show or edit.

And for classes: everywhere in Rails, and generally speaking in Ruby, they would always be singular, and uppercase'd.

Optional parens in Ruby for method with uppercase start letter?

This is just part of Ruby's ambiguity resolution.

In Ruby, methods and variables live in different namespaces, therefore there can be methods and variables (or constants) with the same name. This means that, when using them, there needs to be some way to distinguish them. In general, that's not a problem: messages have receivers, variables don't. Messages have arguments, variables don't. Variables are assigned to, messages aren't.

The only problem is when you have no receiver, no argument and no assignment. Then, Ruby cannot tell the difference between a receiverless message send without arguments and a variable. So, it has to make up some arbitrary rules, and those rules are basically:

  • for an ambiguous token starting with a lowercase letter, prefer to interpret it as a message send, unless you positively know it is a variable (i.e. the parser (not(!) the interpreter) has seen an assignment before)
  • for an ambiguous token starting with an uppercase letter, prefer to interpret it as a constant

Note that for a message send with arguments (even if the argument list is empty), there is no ambiguity, which is why your third example works.

  • test(): obviously a message send, no ambiguity here
  • test: might be a message send or a variable; resolution rules say it is a message send
  • Test(): obviously a message send, no ambiguity here
  • self.Test: also obviously a message send, no ambiguity here
  • Test: might be a message send or a constant; resolution rules say it is a constant

Note that those rules are a little bit subtle, for example here:

if false
foo = 'This will never get executed'
end

foo # still this will get interpreted as a variable

The rules say that whether an ambiguous token gets interpreted as a variable or a message send is determined by the parser and not the interpreter. So, because the parser has seen foo = whatever, it tags foo as a variable, even though the code will never get executed and foo will evaluate to nil as all uninitialized variables in Ruby do.

TL;DR summary: you're SOL.

What you could do is override const_missing to translate into a message send. Something like this:

class DemoClass
def test; puts "output from test" end
def Test; puts "output from Test" end

def run
puts "Calling 'test'"
test()
puts "Calling 'test'"
test
puts "Calling 'Test()'"
Test()
puts "Calling 'Test'"
Test
end

def self.const_missing(const)
send const.downcase
end
end

demo = DemoClass.new
demo.run

Except this obviously won't work, since const_missing is defined on DemoClass and thus, when const_missing is run, self is DemoClass which means that it tries to call DemoClass.test when it should be calling DemoClass#test via demo.test.

I don't know how to easily solve this.

Ruby determining whether a letter is uppercase or not

You can use POSIX character classes:

  • /[[:lower:]]/ - Lowercase alphabetical character
  • /[[:upper:]]/ - Uppercase alphabetical

Example:

def which_case(letter)
case letter
when /[[:upper:]]/
:uppercase
when /[[:lower:]]/
:lowercase
else
:other
end
end

which_case('a') #=> :lowercase
which_case('ä') #=> :lowercase
which_case('A') #=> :uppercase
which_case('Ä') #=> :uppercase
which_case('1') #=> :other

Or with a simple if statement:

puts 'lowercase' if /[[:lower:]]/ =~ 'a'
#=> lowercase

Ruby : uninitialized constant

From Ruby user's guide:

A constant has a name starting with an uppercase character.

It should be assigned a value at most once.

Just change to lowercase it will work:

def test()
puts wb_a
end

# Top level components
def wb_a
{
'A' => 'Apple',
}
end

test()
#=> {"A"=>"Apple"}

Or, if you will, wB_A works too, but not recommended, check tadman's comment below.



Related Topics



Leave a reply



Submit