0

pretty new to ruby and object oriented programming in general. Looking for the Ruby Way of things.

I want to know how to package objects into an array so that I can iterate over them in another class

Currently I am doing it manually with:

bags = []
bag1 = Bag.new("large")
bag2 = Bag.new("medium")
bag3 = Bag.new("small")
bag4 = Bag.new("large")
bags << bag1 
bags << bag2
bags << bag3
bags << bag4

But I feel there must be a better way to do this assignment automatically. Should I create a separate Bags class and do it there? Or is this the best approach? Or should I add a bags method in Customer? Not entirely sure how to go about this in the most elegant way?

Here is all my code:

class Customer

    def bag_check(bags)
        bags.each do |bag| 
            puts bag.size 
        end
    end

end


class Bag
attr_reader :size

    def initialize(size)
        @size = size
    end

end

bags = []
bag1 = Bag.new("large")
bag2 = Bag.new("medium")
bag3 = Bag.new("small")
bag4 = Bag.new("large")
bags << bag1 
bags << bag2
bags << bag3
bags << bag4

customer = Customer.new 
customer.bag_check(bags)

What would be your approach? also I would appreciate any insight into how to think about the problem in addition to code, so that I can know how to approach a problem the next time I face something similar. Thanks!

coderwannabe2
  • 221
  • 1
  • 2
  • 12

3 Answers3

1

A simple map would be sufficient to create an Array containing Bags of the sizes you want.

bags = %w(large medium small large).map { |size| Bag.new(size) }

It is one of the easier operations to wrap your head around, since it takes an Array of size n, and returns another Array of the same size, with some operation performed on each element.

Invokes the given block once for each element of self. Creates a new array containing the values returned by the block.

Drenmi
  • 8,492
  • 4
  • 42
  • 51
0
bags = %w(large medium small large).inject([]) {|bags, bag| bags << Bag.new(bag)}
customer = Customer.new 
customer.bag_check(bags)

http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-inject

What does %w(array) mean?

Community
  • 1
  • 1
djsmentya
  • 315
  • 1
  • 12
0

since Customer has many Bags, this means Customer should have an attribute to store the list of its bags. then it can do whatever it like to these bags. So the Ruby way to implement this can be done as follows.

class Customer
  attr_reader :bags

  def initialize
     @bags = []
  end

  def add_bag bag_size
    bag = Bag.new(size: bag_size, customer: self)
    @bags.push bag
  end

  def bag_check
    bags.each do |bag| 
      puts bag.size 
    end
  end
end

class Bag
   attr_reader :size, :customer

   def initialize attributes
      @size = attributes[:size]
      @customer = attributes[:customer]
   end
end

when you need to add a bag to the Customer you just provide the size of the bag.

customer = Customer.new
%w(large medium small large).each { |size| customer.add_bag(size) }
Nafaa Boutefer
  • 2,169
  • 19
  • 26
  • Hmmm in this case isn't Customer dependent on Bag. Wouldn't you prefer to remove the dependency on bag by introducing a duck type? – coderwannabe2 May 04 '15 at 05:34
  • When I tried this I am getting this error: lockers.rb:64:in `add_bag': undefined method `push' for nil:NilClass (NoMethodError) from lockers.rb:103:in `block in
    ' from lockers.rb:102:in `each' from lockers.rb:102:in `
    '
    – coderwannabe2 May 04 '15 at 05:45
  • This error is because the `@bags` variable has not been initialized. I do initialize it now. – Nafaa Boutefer May 04 '15 at 10:39