Methods and :parameters

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

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

Thanks

···

--
-------------------------------------
Pedro Del Gallego

Email : pedro.delgallego@gmail.com

Pedro Del Gallego 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
method `title' 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

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.

···

On 2/26/07, Pedro Del Gallego <pedro.delgallego@gmail.com> wrote:

Message-ID: <2e93189b0702251757p34aca575v4b8bc41ad115d330@mail.gmail.com>

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

For example,

···

From: "Pedro Del Gallego" <pedro.delgallego@gmail.com>
Subject: Methods and :parameters
Date: Mon, 26 Feb 2007 10:57:59 +0900
-------------------------------------------------------------------
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 = 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
-------------------------------------------------------------------
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

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.

···

On Mon, 26 Feb 2007 10:57:59 +0900, Pedro Del Gallego 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"

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

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

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

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)
    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

Thanks again.

···

--
-------------------------------------
Pedro Del Gallego

Email : pedro.delgallego@gmail.com

Message-ID: <2e93189b0702260502k2fed81b8qbc49ca40b1c89e95@mail.gmail.com>

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?

···

From: "Pedro Del Gallego" <pedro.delgallego@gmail.com>
Subject: Re: Methods and :parameters
Date: Mon, 26 Feb 2007 22:02:56 +0900
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Are those OK?

Perfect :). Thanks a lot.

···

--
-------------------------------------
Pedro Del Gallego

Email : pedro.delgallego@gmail.com