16 Sep 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