Learning ruby part 2 Classes and methods

Learning ruby part 2 Classes and methods

In this tuto we will see some topics like:

  • Optional arguments
  • How to declare methods
  • How to use attr_accessor, attr_writer, attr_reader
  • How to use Clases
  • How to pass hash arguments to methods
  • How to use exceptions
  • How to override methods and reopening clases
  • Using self

Optional arguments: 


def post(message, lat, long)

end

post("hello all the worls", nil, nil)

And we can do this too:


def post(message, lat= nil, long= nil)

end
post(meessage, 24, 25)
or
post("message")

Hash arguments


def post(message, options = {})

  status = Status.new
  status.lat = options[:lat]
  status.long = options[:long]
  status.reply = option[:reply_to]

end

Then we can use

post("practicing ruby",
     :lat => 23,
     :long=> 34,
     :reply_to => "heriberto.perez@crowdint.com")

Or using the syntaxis in ruby 1.9

post("practicing ruby",
      lat: 23,
      long: 34,
      reply_to: "heriberto.perez@crowdint.com")

The keys are optional and we can move the position:

post("practicing ruby",
     :reply_to => "heriberto.perez@crowdint.com",
     :long=> 34)

Or simply:

post("practicing ruby")

Exceptions
We have the next code:


def get_posts(list)
 if list.authorized(@user)
   list.posts
 else
 []
 end
end

posts = get_posts(my_list)
if  posts.empty?
  alert "No post were found " + "Are you authorized to access this list?"
end

Now we use exceptions


def get_posts(list)
  unles  list.authorized(@user)
   raise AuthorizationException.new
  end
  list.posts
end

begin
  posts = get_posts(my_list)
  rescue  AuthorizationException
  warn "you are not authorized to access this list"
end

Now let’s continue with the splat argument in ruby:


def mention(status, *names)
post("#{names.join(' ')} say {#status}")
 end

mention("the post is great", "heriberto", "laura", "jovita", "someone")

#print heriberto laura jovita someone say the post is great

Now let’s to see Classes:

In this examples first without using a class


user_name = [["heriberto", "perez"],
            ["claudia", "cecilia"],
            ["Alma"]]

user_name.each {|n| puts "#{n[0]}, #{n[1]}"}

The before code will print:


heriberto, perez
 claudia, cecilia
 Alma,

Now let’s gonna use a one Class


class Name
 def initialize first = nil, last = nil
   @first = first
 @last = last
 end

  def format

 [@first, @last].compact.join(", ")
end
end

names = []
names << Name.new("heriberto", "perez")
names << Name.new("alma", "perez")
names << Name.new("jose")
names << Name.new("roberto", "perez")
names << Name.new("heriberto")

names.each {|n| puts "#{n.format}"}

This will print out:


heriberto,perez
alma, perez
jose
roberto, perez
heriberto

If you write:

attr_writer :age

That gets translated into:

def age=(value)
  @age = value
end

If you write:

attr_reader :age

That gets translated into:

def age
 @age
end

If you write:

attr_accessor :age

That gets translated into:

def age=(value)
  @age = value
end
def age
  @age
end

Now we use the next example use the before:

class Test
  attr_accessor :age
  attr_reader :name
  def initialize()
  end

  def return_name
   puts @age
  end
end

minombre = Test.new
minombre.age = 24
puts minombre.return_name

Reopening Classes

If we run the code before using the class


post = Test.new
post.to_s

This will print


#<Test:0x991ed18>

But if we want, we can change and override the function to_s if we define that in our class like the next, later we can use that:


class Test
def to_s
 puts "test"
end
end
testing = Test.new
testing.to_s

This will print

test

Using self

if we run some code like:

class Post
attr_accessor :name

 def initialize(name = nil)
  name = name
 end

end

post = Post.new("Excelent tutorial")
puts post.name

This will print nothing because we’re not using @name or self.name but if we use:


class Post
attr_accessor :name

 def initialize(name = nil)
  self.name = name
  #or @name = name
 end
end

post = Post.new("Excelent tutorial")
puts post.name

This will print

Excelent tutorial

Optional Arguments
We’ll store a little more information about our games than just the name. Optional arguments are important for a flexible interface. Let’s change our new_game method so it can be called without passing in year or system.

def new_game(name, year, system)
 {
name: name,
year: year,
system: system
 }
end
game = new_game("Street Figher II", nil, nil)

the solution


def new_game(name, year = nil, system = nil)
 {
 name: name,
 year: year,
 system: system
 }
end
game = new_game("Street Figher II")

Options Hash Argument
Defaulting two arguments to nil isn’t ideal. Update the method signature and implementation to take an optional options hash with keys for :year and :system.

Origin code:

def new_game(name, year=nil, system=nil)
 {
 name: name,
 year: year,
 system: system
 }
end
game = new_game("Street Figher II", "SNES", 1992)

Final Code:

def new_game(name, options={})
 {
 name: name,
 year: options[:year],
 system: options[:system]
 }
end
game = new_game("Street Figher II",
 year: 1992,
 system: "SNES")

Raise Exception
We want to make sure that each game is a valid game object – in this case a simple hash of values. Even still, we wouldn’t want to return a hash with a nil name. Raise an InvalidGameError error in the new_game method if name is nil.

origin code:

class InvalidGameError < StandardError; end
def new_game(name, options={})
 {
 name: name,
 year: options[:year],
 system: options[:system]
 }
end
begin
 game = new_game(nil)
rescue InvalidGameError => e
 puts "There was a problem creating your new game: #{e.message}"
end

Final code:

class InvalidGameError < StandardError; end
def new_game(name, options={})
 {
 name: name,
 year: options[:year],
 system: options[:system]
 }
 if name == nil
 raise InvalidGameError.new
 end
end
begin
 game = new_game(nil)
rescue InvalidGameError => e
 puts "There was a problem creating your new game: #{e.message}"
end

Splat Arguments
When passing in an array of arguments to a method, sometimes it’ll make sense to use Ruby’s “splat” operator rather than explicitly requesting an array. Update the describe_favorites method and the call to it to instead use the splat operator.

Origin Code:


def describe_favorites(games)
 for game in games
 puts "Favorite Game: #{game}"
 end
end
describe_favorites(['Mario', 'Contra', 'Metroid'])

Final Code:

def describe_favorites(*games)
 for game in games
 puts "Favorite Game: #{game}"
 end
end
describe_favorites('Mario', 'Contra', 'Metroid')

Class
Passing around hashes is getting troublesome, let’s use a class to hold our data. We’ve started the Game class for you, now please implement the initialize method to store name, system and year in instance variables:

Origin Code:

class Game
 def initialize(name, options={})
 @name = name
 @system = options[:system]
 @year = options[:year]
 end
end

attr_accessor
Whoever created the game object will want to be able to access the name, year and system for the game, but that doesn’t mean we need to make getter methods for them. Refactor the code below to make these variables available using the Ruby way with attr_accessor.

Origin code:

class Game
 def initialize(name, options={})
 @name = name
 @year = options[:year]
 @system = options[:system]
 end

def name
 @name
 end

def year
 @year
 end

def system
 @system
 end
end

Final Code:

class Game
 attr_reader :name, :system, :year
 def initialize(name, options={})
 @name = name
 @year = options[:year]
 @system = options[:system]
 end
end

attr_reader
When a game is initialized, store another variable called created_at which is set to Time.now in the initialize method. Make sure it can be accessed, but that it cannot be set from outside the object.

Origin Code:

class Game
 attr_accessor :name, :year, :system

def initialize(name, options={})
 @name = name
 @year = options[:year]
 @system = options[:system]
 end
end

Final Code:

class Game
 attr_accessor :name, :year, :system
 attr_reader :created_at
 def initialize(name, options={})
 @name = name
 @year = options[:year]
 @system = options[:system]
 @created_at = Time.now
 end
end

 

No Comments

Post A Comment