What does the equal ('=') symbol do when put after the method name in a method definition?

Ruby

Ruby Problem Overview


I saw this in a screencast and was just wondering what the '=' symbol does in this case.

def express_token=(token)
...
end

I would understand if it were something like this -

def express_token(token = nil) 

The above (second code snippet) means setting nil as the default value of the tokens parameter. However, in the first code snippet, '=' is outside the brackets.

Ruby Solutions


Solution 1 - Ruby

That snippet defines a Virtual Attribute (or a "setter" method) so that "express_token" looks like an attribute, even though it's just the name of the method. For example:

class Foo
  def foo=(x)
    puts "OK: x=#{x}"
  end
end
f = Foo.new
f.foo = 123 # => 123
# OK: x=123

Note that the object "f" has no attribute or instance variable named "foo" (nor does it need one), so the "foo=" method is just syntactic sugar for allowing a method call that looks like an assignment. Note also that such setter methods always return their argument, regardless of any return statement or final value.

If you're defining a top-level setter method, for example, in "irb", then the behavior may be a little confusing because of the implicit addition of methods to the Object class. For example:

def bar=(y)
  puts "OK: y=#{y}"
end
bar = 123 # => 123, sets the variable "bar".
bar # => 123
Object.new.bar = 123 # => 123, calls our method
# OK: y=123
Object.public_methods.grep /bar/ # => ["bar="]

Solution 2 - Ruby

Those methods let you set instance vars in a more indirect way: imagine you have a class Person

class Person < ActiveRecord::Base
  attr_accessible :first_name, :last_name

  def full_name
    [@first_name, @last_name].join
  end

  def full_name=(name)
    @first_name, @last_name = name.split(" ")
  end
end

Then you can do something like this:

p = Person.new
p.full_name = "John Doe"
p.first_name # => "John"
p.last_name # => "Doe"
p.full_name # => "John Doe"

Solution 3 - Ruby

Let's take a look at the following example:

class NewDog  
  def initialize(breed)  
    @breed = breed  
  end

  # create reader only
  attr_reader :breed, :name 

  # setter method  
  def set_name(nm)  
    @name = nm  
  end  
end  

nd = NewDog.new('Doberman')  
nd.set_name('Benzy')  
puts nd.name  

If you refactor the setter method to this:

def name=(nm)  
  @name = nm  
end 

other programmers know that the name= method behaves as a setter method. Also as show by @maerics it behaves like a virtual attribute.

The result looks like this:

class NewDog  
  def initialize(breed)  
    @breed = breed  
  end  

  # create reader only  
  attr_reader :breed, :name 
  
  # setter method  
  def name=(nm)  
    @name = nm  
  end  
end  
  
nd = NewDog.new('Doberman')  
nd.name = 'Benzy'  
puts nd.name 

Solution 4 - Ruby

Its actually part of the name of the function. So it's a setter, in case you need separate functionality than default for getters and setters.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionredshift5View Question on Stackoverflow
Solution 1 - RubymaericsView Answer on Stackoverflow
Solution 2 - RubyAlberto SantiniView Answer on Stackoverflow
Solution 3 - RubyPeter PiperView Answer on Stackoverflow
Solution 4 - RubyYuleView Answer on Stackoverflow