0

I have been working with Ruby for three days. I am trying to set a default in the way shown below, for #happiness. i need #happiness to have a range of 0-10, cannot be less than zero or more than ten. Thanks in advance.

class Person
    attr_reader :name
    attr_accessor :bank_account, :happiness={value > 11}
    
    def initialize(name)
        @name = name
        @bank_account = 25
        @happiness = 8
    end
end
Stefan
  • 109,145
  • 14
  • 143
  • 218
Michael
  • 169
  • 3
  • 11
  • 1
    You can't do that with [Module#attr_accessor](https://ruby-doc.org/core-2.7.0/Module.html#method-i-attr_accessor) or [Module#attr_writer](https://ruby-doc.org/core-2.7.0/Module.html#method-i-attr_writer). Both merely create the *setter* method `def happiness(v); @happiness = v; end`. (`attr_accessor` also creates the *getter* `def happiness; @happiness; end`). You must define the method yourself, perhaps `def happiness(v); raise "#{v} out of range" unless (0..10).cover?(v); @happiness = v; end`. – Cary Swoveland Jan 13 '22 at 07:11
  • 1
    @CarySwoveland I suggest making this comment an answer. It is a great suggestion and it would be much easier to read and understand. – spickermann Jan 13 '22 at 09:48

1 Answers1

2

If you need a writer method that performs some validation, then you have to write a writer method which performs that validation. For example, something like this:

class Person
  attr_reader :name, :happiness
  attr_accessor :bank_account

  def initialize(name)
    @name = name
    @bank_account = 25
    @happiness = 8
  end

  def happiness=(value)
    raise ArgumentError, "`happiness` needs to be between 0 and 10, but you supplied `#{value}`" unless 0..10 === value
    @happiness = value
  end
end
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 2
    if happiness should not raise an error but just be silently maximized at 10 or minimized at 0, there is `clamp` : @happiness = value.clamp(0, 10) – steenslag Jan 13 '22 at 11:11
  • `unless value.between?(0, 10)` might be a bit cleaner – Stefan Jan 13 '22 at 12:48
  • 1
    BTW, for someone _"working with Ruby for three days"_ it might not be obvious what `attr_accessor` does or that you can / need to implement your own "writer method". Maybe you could include some further explanation. – Stefan Jan 13 '22 at 13:29