1

I created a class and added objects like so:

class Tops
  def initialize(neckline, brand, maincolour, style)
    @neckline = neckline
    @brand = brand
    @maincolour = maincolour
    @style = style
  end
end

top1 = Tops.new("Sweetheart", "Miss Selfridge", "Blue", "Bardot")
top2 = Tops.new("Scoop", "Target", "Pink", "Vest")
top3 = Tops.new("Boat", "Unknown", "Red", "Tank")

I then used the push method to add some of these objects into an empty array.

currentTopChoices = []
currentTopChoices.push(top1,top3)

I then used some the each method to run a block of code or each object in this array

currentTopChoices.each { |x| puts @neckline }

So my aim was really to get an output of each neckline of the objects in the array but I get an output of:

Boat
Boat

When I really wanted:

Sweetheart
Boat

Which is really the neckline of the last object but printed twice. I get no error messages so what exactly am I missing here?

2
  • just make a setter or add a attr_accessor then use map for the new array. Commented Sep 2, 2016 at 21:12
  • 1
    I cannot reproduce this. Since @neckline is un-initialized, it should evaluate to nil and thus print two empty lines, not Boat. Commented Sep 3, 2016 at 8:23

2 Answers 2

1

If you don't mind adding an attr_accessor to Tops (which will provide a Top#neckline accessor method), you can use Array#map or (its alias Array#collect) to build a collection of necklines:

class Tops
  attr_accessor :neckline

  def initialize(neckline, brand, maincolour, style)
    @neckline = neckline
    @brand = brand
    @maincolour = maincolour
    @style = style
  end
end

top1 = Tops.new("Sweetheart", "Miss Selfridge", "Blue", "Bardot")
top2 = Tops.new("Scoop", "Target", "Pink", "Vest")
top3 = Tops.new("Boat", "Unknown", "Red", "Tank")

[top1, top3].map(&:neckline) # => ["Sweetheart", "Boat"]
# or, more explicitly
[top1, top3].map { |top| top.neckline } # => ["Sweetheart", "Boat"]
Sign up to request clarification or add additional context in comments.

Comments

1

The problem is that somehow you are confusing yourself by either not showing all your code, or maybe running this in irb, where at some point you had a statement like?

@neckline = "Boat"

For example the code you posted, if placed directly in a file_name.rb like so:

class Tops
  def initialize(neckline, brand, maincolour, style)
    @neckline = neckline
    @brand = brand
    @maincolour = maincolour
    @style = style
  end
end

top1 = Tops.new("Sweetheart", "Miss Selfridge", "Blue", "Bardot")
top2 = Tops.new("Scoop", "Target", "Pink", "Vest")
top3 = Tops.new("Boat", "Unknown", "Red", "Tank")

currentTopChoices = []
currentTopChoices.push(top1,top3)

currentTopChoices.each { |x| puts @neckline }

and then run using ruby file_name.rb

would just produce 2 blank lines because @neckline is not define at this scope (toplevel), so it's value is nil

To get this to work the way you intend you can add

attr_reader :neckline

and then refer to x.neckline within the block you pass to each, since x will take one the value of each of the Tops objects in currentTopChoices

note: attr_accessor adds both a setter and a getter for neckline, if you only need read access to that property than that's all you should allow (which is what you get with attr_reader ), if you really need to both get and set the value of neckline on an instance after creating it then att_accessor would make sense.

Here is an updated version of your code that should behave as you are expecting.

class Tops
  attr_reader :neckline  # added to allow read access to @neckline
  def initialize(neckline, brand, maincolour, style)
    @neckline = neckline
    @brand = brand
    @maincolour = maincolour
    @style = style
  end
end

top1 = Tops.new("Sweetheart", "Miss Selfridge", "Blue", "Bardot")
top2 = Tops.new("Scoop", "Target", "Pink", "Vest")
top3 = Tops.new("Boat", "Unknown", "Red", "Tank")

currentTopChoices = []
currentTopChoices.push(top1,top3)

currentTopChoices.each { |x| puts x.neckline }  # access the neckline property for each element

Comments

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.