Forum: Ruby class returns value without method or attribute

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
kris (Guest)
on 2006-04-28 18:39
If I have a class how do I get it to return a value without specifying a
method or attribute:

class Money
  attr_writer :value
end


money = Money.new(5)

money.value => 5

but what if I want:

money => 5

So the actual object returns a value instead of a method or attribute,
like the base classes do.

Many thanks, K.
Farrel L. (Guest)
on 2006-04-28 19:00
(Received via mailing list)
You could overload the  methods you require.  For instance if you want
to be able to add two Money objects togeter and get a Money object as
the result using the expression 'money1 + money2' you could do

>> class Money
>>   attr_accessor :value
>>   def+(other)
>>     Money.new(@value + other.value)
>>   end
>>   def initialize(value)
>>     @value = value
>>   end
>> end
=> nil
>> m1 = Money.new(5)
=> #<Money:0x2dbb018 @value=5>
>> m2 = Money.new(10)
=> #<Money:0x2db9098 @value=10>
>> m1 + m2
=> #<Money:0x2db17d8 @value=15>

Farrel
Gordon T. (Guest)
on 2006-04-28 19:19
(Received via mailing list)
>If I have a class how do I get it to return a value without specifying a
>method or attribute:
>

You want to overload the inspect method:

class Money
  attr_accessor :value

  def initialize(value)
    @value = value
  end

  def inspect
    @value
  end

end

irb(main):001:0> require 'money'
=> true
irb(main):002:0> money = Money.new(5)
=> 5
irb(main):003:0> money
=> 5
13 (Guest)
on 2006-04-28 19:19
(Received via mailing list)
Hi,

Here is my approach (similar, but longer):

$ cat money.rb

class Money
  attr_accessor :value

  def initialize(value)
    @value = value
  end

  def to_s
    @value.to_s
  end

  def +(other)
    case other
      when Money:
        Money.new(@value + other.value)
      when Numeric:
        Money.new(@value + other)
      else
        raise "Money can be added to Money or Numeric"
    end
  end
end

irb(main):002:0> money = Money.new 5
=> #<Money:0x2ba41c8 @value=5>
irb(main):004:0> puts money
5
irb(main):005:0> puts money + money
10
irb(main):006:0> puts money + 100
105
irb(main):007:0> puts money + 'money'
RuntimeError: Money can be added to Money or Numeric
        from ./money.rb:19:in `+'
        from (irb):7

--
Martins
Ross B. (Guest)
on 2006-04-28 19:28
(Received via mailing list)
On Fri, 2006-04-28 at 23:39 +0900, kris wrote:
> money.value => 5
>
> but what if I want:
>
> money => 5
>
> So the actual object returns a value instead of a method or attribute,
> like the base classes do.

Another way to get this kind of behaviour is:

require 'delegate'
Money = DelegateClass(Float)
m = Money.new(30.0)

p m
>> 30.0
p m + 30.0
>> 60.0
p m + Money.new(30.0)
>> 60.0
p m.class
>> Money
p m.__getobj__.class
>> Float
p m + "notmoney"
kris (Guest)
on 2006-04-29 13:52
I like the idea of using inspect, will this also allow me to assign
value like:
money = Money.new
money = 5

Also do I need to add a method for + and -, is there not a module like
Comparable that I can mixin to get this functionality?

Are there any other typical methods I should be adding? Excluding the
money specific stuff I have to_s.

Many thanks for all the replies they have been really helpful.


Gordon T. wrote:
>>If I have a class how do I get it to return a value without specifying a
>>method or attribute:
>>
>
> You want to overload the inspect method:
>
> class Money
>   attr_accessor :value
>
>   def initialize(value)
>     @value = value
>   end
>
>   def inspect
>     @value
>   end
>
> end
>
> irb(main):001:0> require 'money'
> => true
> irb(main):002:0> money = Money.new(5)
> => 5
> irb(main):003:0> money
> => 5
Robert K. (Guest)
on 2006-05-03 21:08
(Received via mailing list)
2006/4/29, kris <removed_email_address@domain.invalid>:
> I like the idea of using inspect, will this also allow me to assign
> value like:
> money = Money.new
> money = 5

No, inspect will only affect output with p (or in IRB).

> Also do I need to add a method for + and -, is there not a module like
> Comparable that I can mixin to get this functionality?

Comparation and arithmetic are two orthogonal concepts, i.e.
completely unrelated. If you want arithmetic in your class, you need
to override +, - and coerce.

http://www.rubygarden.org/ruby?CoerceExplanation
http://www.rubygarden.org/?terms=coerce&submit=SEA...

For ordering there is mixin Comparable
http://ruby-doc.org/core/classes/Comparable.html
http://www.rubycentral.com/book/ref_m_comparable.html

> Are there any other typical methods I should be adding? Excluding the
> money specific stuff I have to_s.

to_int is an option, too, if your instance is equivalent to an int.
Additionally you should implement to_i and to_f.

Kind regards

robert
This topic is locked and can not be replied to.