views:

320

answers:

3

I'm running the following method and I'm successfully passing two arguments (inventory, quantity) into the method. However I'm incorrectly using .first and .each methods. I'm attempting to replace .each with the .select to select for the cart item with the Inventory id: 6

possible .each replacement: (does not function) inventory_to_increment = @items.select{|item| item_id == inventory}

def increment_inventory_quantity(inventory, quantity)
   inventory_to_increment = @items.each{|item| item.inventory == inventory}
   unless inventory_to_increment.empty?
      inventory_to_increment = inventory_to_increment.first
   else
      # error handling here
   end
   inventory_to_increment.quantity = quantity.to_i
end

I've used Ruby Debugger, to debug my code:

inventory_to_increment = @items.each{|item| item.inventory == inventory}

p inventory = 6

unless inventory_to_increment.empty?

CartItem:0x102c4a4c0 @quantity=22, @inventory=#<Inventory id: 1

CartItem:0x102c49638 @quantity=2, @inventory=#<Inventory id: 8

CartItem:0x102c48918 @quantity=4, @inventory=#<Inventory id: 50

CartItem:0x102c47b80 @quantity=2, @inventory=#<Inventory id: 6

inventory_to_increment.first

CartItem:0x102c4a4c0 @quantity=22, @inventory=#<Inventory id: 1 

inventory_to_increment.quantity = quantity.to_i

= 3

I've tried several combinations and I need some basic Ruby array guidance. Thank you in advance!

UPDATE OUTPUT FOR ANSWER

inventory_to_increment = @items.select{|item| item.inventory_id == inventory}
(rdb:1) list
[21, 30] in /Users/justin/cart/app/models/cart.rb
   21   
   22  
   23  def increment_inventory_quantity(inventory, quantity)
   24  debugger
   25  
=> 26     inventory_to_increment = @items.select{|item| item.inventory_id == inventory}
   27   unless inventory_to_increment.empty?
   28       inventory_to_increment.first
   29   end
   30  
(rdb:1) p @items
[#<CartItem:0x102df1828 @quantity=22, @inventory=#<Inventory id: 1>>, #<CartItem:0x102df09a0 @quantity=2, @inventory=#<Inventory id: 8>>, #<CartItem:0x102ded908 @quantity=21, @inventory=#<Inventory id: 50>>]
(rdb:1) p inventory
50
(rdb:1) p quantity
"11"
(rdb:1) p item.inventory.id
NameError Exception: undefined local variable or method `item' for #<Cart:0x102df18f0>
(rdb:1) p item.inventory_id
NameError Exception: undefined local variable or method `item' for #<Cart:0x102df18f0>
(rdb:1) next
/Users/justin/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/rescue.rb:162
rescue_action(exception)
+1  A: 

You might want to use Enumerable#find instead of what you have here, since you're trying to select a single element from an Array. That would be a "find and increment" approach.

The alternative is to simply use the each iterator to increment any matching inventories, where if the assumption is there will only be one, then there is no concern about duplication:

def increment_inventory_quantity(inventory, quantity)
   @items.each do |item|
     if (item.inventory == inventory)
       item.inventory.quantity += 1
     end
   end
end

It's not clear what the inner structure of your various objects is, so I'm presuming you just want to increment here.

tadman
That doesn't seem to work, when I implemented it, it tests the first item from an array (in my test case item 1) then item 1 DNE item 6 and returns false. I chose select because I have an array of inventory objects, I need to select a specific object, "Inventory id: 6" rather than just the first object within the array.
JZ
... of course that is a loop, uh.
JZ
I'm not trying to simply increment (as the name implies). I'm trying to set The selected array item (in your case item.inventory.quantity) equal to the quantity passed as a parameter. When I correct your code above: item.inventory.quantity = quantity.to_i nothing happens at all. what is going on?
JZ
If these are ActiveRecord models, you may need to save the changes or nothing will happen.
tadman
A: 

I think something like the is what you need,

def increment_inventory_quantity(inventory, quantity)
  @items.each { |item| item.quantity += quantity.to_i if item.inventory == inventory }
end
Mike Nelson
+1  A: 

It seems Inventory is an object and if so it's likely that your item.inventory == inventory will not work as expected. Let's say you have an Item class.

class Item
    attr_accessor :inventory_id, :quantity

  def initialize(inventory_id, quantity)
    @inventory_id = inventory_id
    @quantity = quantity
  end
end

and then you create two objects and compare them:

>> item1=Item.new(8,2)
=> #<Item:0xb7b733bc @inventory_id=8, @quantity=2>
>> item2=Item.new(8,2)
=> #<Item:0xb7b6b7c0 @inventory_id=8, @quantity=2>
>> item1==item2
=> false

This is because you will compare the object ids (0xb7b733bc to 0xb7b6b7c0) instead of the content of the objects.

>> item1.inventory_id==item2.inventory_id
=> true

It then seems you only want to add to the quantity to the first item matching the inventory id. If that is correct then you can try something like this

 inventory_to_increment=items.select {|item| item.inventory.inventory_id==inventory}
 unless inventory_to_increment.empty?
    inventory_to_increment.first.quantity+=quantity
 end
Jonas Elfström
I'm not sure it makes a difference that I'm rails, but I've followed your advice and added the output above. You can see that I changed items to @items and inventory.id to inventory
JZ
I changed to `item.inventory.inventory_id` to follow Rails ActiveRecord convention.
Jonas Elfström
Thank you! what a headache this problem has been
JZ
With a few mods it works....inventory_to_increment = items.select {|item| item.inventory.id == inventory} unless inventory_to_increment.empty? inventory_to_increment.first.quantity = quantity.to_i end
JZ