Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Ruby Objects and Classes Variables and Methods Attribute Writers and Accessors

Nick Vitsinsky
Nick Vitsinsky
7,246 Points

Why def title=(new_title) and not def title(new_title)?

Why we should define method and argument as

def title=(new_title)

and not

def title(new_title)

And how in future to define where to put "=" and where not?

3 Answers

Carsten Jaksch
Carsten Jaksch
5,847 Points

In my understanding, this equal sign allows a method call with equal sign like obj.method = value. I think it's only be used within classes to define writer or setter methods.

This is also a convention in Ruby, that explains the use of a method – in this case setting an instance variable. So that other programmers can see what a method is for, just by looking at the method name.

But for the future, just use attr_reader, attr_writer or attr_accessor. It's simpler.

Nick Vitsinsky
Nick Vitsinsky
7,246 Points

Yeah, I'm going to use attr_reader, attr_writer and attr_accessor

so as I understand in case I use 'def title=(new_title)' I assign a value to a method (the question why would I want to) and in this case 'def title(new_title)' I tell an argument of the method. That's clear for me. But, the thing why and what cases might be for assigning a value and\instead of setting an argument, and what is the difference are still open

Carsten Jaksch
Carsten Jaksch
5,847 Points

Yes, you can write it with or without an equal sign, but it's still Ruby convention to add the equal sign for setter methods. So you tell other programmers just with the method title: This is a setter method, it sets the value of an instance variable.

Here you can read more about "syntactic sugar" in Ruby: http://rubylearning.com/satishtalim/ruby_syntactic_sugar.html Quote: "The equal sign gives you that familiar "assigning a value to something" feeling, so you know you're dealing with a setter method."

You could do this thing, too: obj.method=(value) instead of obj.method = value

It's just up to you, how to write this methods (with or without =). But it's a convention to write setter methods with equal sign.

Chufan Xiao
Chufan Xiao
18,955 Points

Thanks for the explanation, I was confused by that too

Greetings, ima break it down in lay man terms!

#in Ruby we have a way to talk about objects and their attributes ina yummy way anyone can relate to. 

#syntactic sugar vs syntactic vinegar

#syntactic vinegar for setting the instance method's title inside our Name class : 

person.tile=("Dr.") # That looks a lot like the method definition!

#syntactic sugar :

person.title = "Dr." # <<< this is the (value) passed in to the title instance method's parameter ( the parentheses next to the method name)


#both ways are the same thing, ruby gives you a nice way to code without  the ()

#note that behind the hood meaning inside the logic in ruby everytime you use a macro like an attr_reader, writer or accessor(both) the setter always uses a = 

#in fact your initialize instance method uses this = 

def initialize=(title)
  #your code here
end 

# we just are lazy by nature (in a good way) and write it like so:

class Name

    def initialize(title)
        @title = title
    end 

##We've already seen new instances of classes being created with the #new method. For example:

class Dog
end

snoopy = Dog.new #=> #<Dog:0x007f970a2edfd0>


#The code above creates a new instance of the Dog class and sets that object equal to a variable, snoopy. If we want to give our dog a breed, we have to use the following code:

class Dog
  def breed=(breed)
    @breed = breed
  end

# the above sets the value 
#A setter method is defined with an =, equals sign, appended to the name of the method. The = is followed by the (argument_name). 
#The syntax highlighting may make it look like the = sign in breed= is separate from the name of the definition, but it is not. The = is a necessary piece. 

  def breed
    @breed
  end

#the above reads the value  

#The methods act as mechanisms to expose data from inside of the object to the outside world.




end

snoopy = Dog.new #=> #<Dog:0x007f970a2edfd0>
snoopy.breed #=> nil
snoopy.breed = "Beagle"
snoopy.breed #=> "Beagle"


#Classes are the blueprints that define the behavior and information our objects will contain. They let us manufacture and instantiate new instances.


#However, most dogs are born with a breed, not assigned a breed afterwards. This is where the initialize instance method comes to save the day!

# in the initialize everytime we use .new and the value passed in goes to the paramater inside the initialize (here)
# we set it using = 
# behind the hood you don't see it but is there 


this is why we use the = vs not using it.


    def title=(value) #<<< value to be passed in we setting the attribute
        @title = "Awesome #{value}"
    end 
end 

#what is the difference bt' =  and not using =  (aka setter method )

# using = means you want to set a value(attribute)

# not using  = means you are just reading (aka getter method)

#how to know when to use which?

# it all depends if you want your class Name  or the Dog class to have attributes that the user can change like breed or title...
# i.e everytime you make an instance of something and you initialize it do you want that instance of that object to be born with a title or  breed? if yes then make it a setter method, you could always change it later to a getter method as you refactor your code. 



#Example 

name = Name.new

# we get this  => #<Name:0x0000564ce24a6f70> 
# that is our new object!

#remember that an object can have attributes

# here our object instance name does not have any attributes

# we get this  => #<Name:0x0000564ce24a6f70>  <<< see no attributes.

# this instance  object of the class Name is just a unique copy.

#try creating another name with a different variable like 

name_two =Name.new

 => #<Name:0x0000564ce245f4b8> 




# look at the numbers aka object ids, you will see they are different. 


name  =>        #<Name:0x0000564ce24a6f70> 

#vs

name_two =>  #<Name:0x0000564ce245f4b8> 


#they are each copies or what we call instances. But really they are objects! Almost everything inside ruby is an object. 

# let's give it an atttribute 

name = Name.new
 => #<Name:0x00005632319c8448> 
name.title = "Dr."
 => "Dr." 
name
 => #<Name:0x00005632319c8448 @title="Awesome Dr.">  # Eyy! (italian accent-) we now have an attribute!
puts name.title 
Awesome Dr.
 => nil # why nil bc puts always return nil 



#the Name class is like the idea of a Mug. And out of the Mug all instances are born! 

name  =>        #<Name:0x0000564ce24a6f70>   << this is an instance of a concept of name


# take your mug look at it, this is also an instance of the class of Mug. 


# every mug is different,  some tall , some round...what is the same is the concept of the Mug.  In ruby the concept is aka as a class

#to assign a an attribute we have to have a setter method inside our class body or else when you try to call 

name.title # you will get an undefined method name error bc the method title is nto set to assign values. so add it inside the class 

class Name

  def initialize(title)
    @title = title
end 

#since you want to be able to change the title attribute write the setter method for ir 

def title=(tittle)
  @title= title
  end 

 def title
    @title
  end 

#and we can call it now 

name_two = Name.new
name_two.title = "Mr."
name_two 
 => #<Name:0x0000564ce245f4b8 @title="Awesome Mr."> 

name= Name.new
name.title = "Dr."
name
 => #<Name:0x0000564ce24a6f70 @title="Awesome Dr."> 

two instances were born from our Name class and although they have similar attributes, i.e, title, they are each their own unique object. We were able to set a value of title thanks to the = assignment operator inside our instance method