Methods and :parameters


#1

Hi all,

I’ve a question about the :parameter notation.
I want to write a method that can hold several optional paramters

add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”
add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”,
:tag=>“novel”
add_book :title=>“El quijote”

and i had write the add_book mehod like this :

class Book
attr_writer :title, :author
end

def add_book (book )
puts “title : #{book.title} – Author : #{book.author}”
end

but the interpreter said : ./bibliom.rb:7:in add_book': undefined methodtitle’ for {:title=>“El quijote”, :author=>“Miguel de
Cervantes”}:Hash (NoMethodError)

I also try to put a hash object in the incoming parameter, like that :

def add_book (book=[]) … end

My question is how can i wirte a method with several optional
parameter and then acces they inside of the mehotd ?

Thanks

Pedro Del G.

Email : removed_email_address@domain.invalid


#2

Pedro Del G. wrote:

I’ve a question about the :parameter notation.
I want to write a method that can hold several optional paramters

add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”
add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”,
:tag=>“novel”
add_book :title=>“El quijote”
To have a method with optional variables, assign them to nil in the
declaration. If they aren’t included in the method call, they will be
set to nil.

def add_book(title, author = nil, tag = nil)

but the interpreter said : ./bibliom.rb:7:in add_book': undefined methodtitle’ for {:title=>“El quijote”, :author=>“Miguel de
Cervantes”}:Hash (NoMethodError)
It gives you this error because you are using attr_writer, which is
equivalent to a def attr= method. In order to simply return a value,
you should use attr_reader, or in case you want both, attr_accessor.

I think what you want is along the lines of:

class Book
attr_accessor :title, :author, :tag

def initialize(title, author = nil, tag = nil)
   self.title = title
   self.author = author
   self.tag = tag
end

def add_book
   puts "title: #{self.title} -- Author: #{self.author}"
end

end


#3

On 2/26/07, Pedro Del G. removed_email_address@domain.invalid wrote:

Hi all,

I’ve a question about the :parameter notation.
I want to write a method that can hold several optional paramters

add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”
add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”,
:tag=>“novel”
add_book :title=>“El quijote”

When you use this kind of argument for a method it is encapulated into
an
anonymous hash. It’s like writing
add_book( { :title=>“El quijote”, :author=> “Miguel de Cervantes”,
:tag=>“novel” } )

and i had write the add_book mehod like this :

class Book
attr_writer :title, :author
end

def add_book (book )
puts “title : #{book.title} – Author : #{book.author}”
end

You’ve added the attr_writer, but you may want to make it into an

attr_accessor

so that you have both reader and writer

Your add_book should look something like, can’t give it to you exactly.
sorri no ruby at work :frowning:

def add_book( book )
title = book[:title] || nil
author = book[:author] || nil
puts “title : #{title} – Author : #{author}”
end

Since book is an Hash, you need to access it as book[:title]. You need
to
assign the book[:title] given to the book object to its own title, the
one
you made the accessor for.

I must say though that I don’t quite understand how you can add_book to
a
book. I would expect to see this as part of an initialize method
instead.
That way you would write

book = Book.new( :title => ‘bla’, :author => ‘author’ )

But that’s just me.

but the interpreter said : ./bibliom.rb:7:in `add_book’: undefined

method `title’ for {:title=>“El quijote”, :author=>“Miguel de
Cervantes”}:Hash (NoMethodError)

I also try to put a hash object in the incoming parameter, like that :

def add_book (book=[]) … end

What this does is sets the local variable book, inside the add_book
method
to an empty array by default. ie if there is no parameter passed then
you
can rely on it being an empty array.


#4

Wow … thats exactly what i was looking for :). Can you explain me
how this override of the method_missing works? im a little bit lost
right after the when statament begin …

  end
when 0
  self[prop]
else
  super(id, *args)
end

end

Thanks again.

Pedro Del G.

Email : removed_email_address@domain.invalid


#5

From: “Pedro Del G.” removed_email_address@domain.invalid
Subject: Re: Methods and :parameters
Date: Mon, 26 Feb 2007 22:02:56 +0900
Message-ID:
removed_email_address@domain.invalid

Wow … thats exactly what i was looking for :). Can you explain me
how this override of the method_missing works? im a little bit lost
right after the when statament begin …

def method_missing(id, *args)

          # Expect the unknown method as accessing to a property.
prop = id.id2name
          # Get the method name string.
case args.length
          # Check the number of arguments.
when 1
          # If one argument, it will be a setter method.
  if prop[-1] == ?=
          # Is it "<property>="? (e.g. "self.property = val")
          # If so, call "self[<property>] = val".
    self[prop[0..-2]] = args[0]
    args[0]
  else
          # Else it will be "self.property(val)".
          # Then call "self[<property>] = val".
    self[prop] = args[0]
    self
  end
when 0
          # If no argument, it will be a getter method.
  self[prop]
else
          # If more than one argument, it will not a setter or 

getter.
# So use “method_missing” of the super class.

  super(id, *args)
end

end

Are those OK?


#6

From: “Pedro Del G.” removed_email_address@domain.invalid
Subject: Methods and :parameters
Date: Mon, 26 Feb 2007 10:57:59 +0900
Message-ID:
removed_email_address@domain.invalid

My question is how can i wirte a method with several optional
parameter and then acces they inside of the mehotd ?

For example,

class Book
def initialize(properties = {})
@props = {
‘title’ => ‘’,
‘author’ => ‘’,
‘tag’ => nil,
‘price’ => nil,
‘ISBN’ => nil,
}

properties.each{|k, v|
  k = k.to_s
  raise ArgumentError, "unknown property: #{k}" unless 

@props.key?(k)
@props[k] = v
}
end

def method_missing(id, *args)
prop = id.id2name
case args.length
when 1
if prop[-1] == ?=
self[prop[0…-2]] = args[0]
args[0]
else
self[prop] = args[0]
self
end
when 0
self[prop]
else
super(id, *args)
end
end

def
prop = prop.to_s
raise ArgumentError, “unknown property: #{prop}” unless
@props.key?(prop)
@props[prop]
end

def []=(prop, val)
prop = prop.to_s
raise ArgumentError, “unknown property: #{prop}” unless
@props.key?(prop)
@props[prop] = val
end
end

def add_book(props)
book = Book.new(props)
puts “case1: title : #{book.title} – Author : #{book.author}”
puts “case2: title : #{book[:title]} – Author : #{book[:author]}”
puts “case3: title : #{book[‘title’]} – Author : #{book[‘author’]}”
book
end

add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”
add_book :title=>“El quijote”, :author=> “Miguel de Cervantes”,
:tag=>“novel”
add_book :title=>“El quijote”

add_book :title=>“hogehoge”, :language=>“Japanese” # => raise
ArgumentError


#7

On Mon, 26 Feb 2007 10:57:59 +0900, Pedro Del G. wrote:

Cervantes"}:Hash (NoMethodError)

I also try to put a hash object in the incoming parameter, like that :

def add_book (book=[]) … end

My question is how can i wirte a method with several optional parameter
and then acces they inside of the mehotd ?

def add_book (book )
puts “title : #{book[:title]} – Author : #{book[:author]}”
end

When using the named parameter idiom, all of the named parameters are
lumped together into a single hash which is passed as the last
parameter.
There’s no point in defining the Book class – it won’t be used by this
idiom.

If you want to access the parameters as members, then you can construct
an OpenStruct inside the method, like so

require ‘ostruct’

def add_book book
book=OpenStruct.new(book)
puts “title : #{book.title} – Author : #{book.author}”
end

but that’s most likely overkill.


#8

Are those OK?

Perfect :). Thanks a lot.

Pedro Del G.

Email : removed_email_address@domain.invalid