0

I am a Ruby beginner. I am confused by an example from Why's Poignant Guide.

I understand the following example's use (also from the Poignant Guide) of picks in initialize, because it is passed in as an argument.

class LotteryTicket

  NUMERIC_RANGE = 1..25

  attr_reader :picks, :purchased

  def initialize( *picks )
    if picks.length != 3
      raise ArgumentError, "three numbers must be picked"
    elsif picks.uniq.length != 3
      raise ArgumentError, "the three picks must be different numbers"
    elsif picks.detect { |p| not NUMERIC_RANGE === p }
      raise ArgumentError, "the three picks must be numbers between 1 and 25"
    end
    @picks = picks
    @purchased = Time.now
  end

end

But how does initialize in the following example start using picks without picks being passed in as an argument? Here, note1, note2, note3 is passed in instead. How does that ever get assigned to picks?

class AnimalLottoTicket

      # A list of valid notes.
      NOTES = [:Ab, :A, :Bb, :B, :C, :Db, :D, :Eb, :E, :F, :Gb, :G]

      # Stores the three picked notes and a purchase date.
      attr_reader :picks, :purchased

      # Creates a new ticket from three chosen notes.  The three notes
      # must be unique notes.
      def initialize( note1, note2, note3 )
        if [note1, note2, note3].uniq!
          raise ArgumentError, "the three picks must be different notes"
        elsif picks.detect { |p| not NOTES.include? p }
          raise ArgumentError, "the three picks must be notes in the chromatic scale."
        end
        @picks = picks
        @purchased = Time.now
      end
end

2 Answers 2

1

That code has an error in it. When I run it in irb I get the following:

NoMethodError: undefined method `detect' for nil:NilClass

There's a discussion here from 2005. If you put the following at the beginning of initialize you'll probably get what they were looking for:

picks = [note1, note2, note3]
if picks.uniq!
Sign up to request clarification or add additional context in comments.

1 Comment

_why gave up on ruby a number of years ago, alas, he's not there to fix things up.
0

Here, picks is not a local variable. It is a method defined by attr_reader :picks, :purchased. The method calls the value of the instance variable @picks. So @picks = picks is the same as @picks = @picks, which is assigning its value to itself, which does not have any effect. I think is was written by a person not familiar with Ruby.

6 Comments

It was written by _why (see link in question)
:attr_reader :picks defines the AnimalLottoTicket.picks() method for getting the @picks variable in the class and declares @ picks. picks, without an @ is a local variable and not saved between instance methods. stackoverflow.com/questions/5046831/…
@PaulRubel No. It doesn't define AnimalLottoTicket.picks. It defines AnimalLottoTicket#picks, which accesses the instance variable @picks. There is no variable declaring in Ruby. If @picks is called without assignment, it would be initialized to nil at that point. Method definition of picks has nothing to do with it.
You're right. I was confused and mistaken. I'd remove my downvote but it won't let me without an edit.
@sawa Could you briefly explain what you mean by there not being any variable declaring in Ruby? Aren't instance variables and class variables declared variables?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.