has through

Hi,

I have 3 models

Product   has_many :mutations

  def current_stock <blablabla here I calculated the current stock of the product> end

Mutation   belongs_to :product   belongs_to :location

Location   has_many :mutations

Question:

I can show the currect stock of a product with

product.current_stock

but how do a walk through all locations and show the different current stock of per location. I was thinkinf of using has many through and the use something like product.current_stock.locations.each etc.

But ofcourse that does not work.

Who can help ?

Correct me if I’m wrong, but is this what you’re looking for?

Product

has_many :locations, :through => :mutations

end

Mutations

belongs_to :product

belongs_to :location

end

Location

has_many :products, :through => :mutations

end

product_stocks = Location.products.collect {|x| x.current_stock}

If you need the name you could do something like

Location.products.each { |product| products[product.name] = product.current_stock }

maybe a newbie question but what if I have a product ID and want to show current_stock in the different locations?

First of all, I’m an idiot because I didn’t include something necessary to make it work Both Product and Location should have has_many :mutations

Secondly, what you’re asking means you want to do something other than what you had in your original post: you want to have a current_stock for each product <-> location relationship… that means current_stock should be part of the Mutation model.

If you want to keep a total current_stock for each product, and a seperate one for each product at each location, then you would want to have current_stock in Location be the sum of the stocks for all the locations, which means your code should now look like:

class Location < ActiveRecord::Base has_many :mutations has_many :locations, :through => :mutations def current_stock Mutations.find_by_product_id(self.id).inject(0) {|total, location_stock| total += location_stock.current_stock}

end end

class Mutation < ActiveRecord::Base belongs_to :location belongs_to :product def current_stock # code to figure out current stock for this product/location end end

class Location < ActiveRecord::Base has_many :mutations has_many :products, :through => :mutations end

And if I weren’t an idiot, this would have said class Product instead of class Location at the top

I guess I am not being clear on what I am looking for :slight_smile:

What I want is for a product X (example: 24710089) to show the current_stock in all locations. Show I should get some array/hash that allows me to output

Product 24710089           Location A: 10           Location C: 20 etc.

Based on examples above this is what I have implemented now:

class Product < ActiveRecord::Base   has_many :mutations   has_many :locations, :through => :mutations

  def current_stock     Mutation.find_all_by_product_id(self.id).inject(0) {|total, mut| total += mut.mutation}   end end

class Mutation < ActiveRecord::Base   belongs_to :product   belongs_to :location

  def mutation     mutation = 0 + self.buy - self.sell - self.transit - self.lost   end end

class Location < ActiveRecord::Base   has_many :mutations   has_many :products, :through => :mutations

  def current_stock       Mutation.find_all_by_location_id(self.id).inject(0) {|total, mut> total += mut.mutation}   end

end

So the solution I am looking for should allow me to input the product_id as the selection criteria then return all locations with the current_stock value. Any tips ?

I guess I am not being clear on what I am looking for :slight_smile:

What I want is for a product X (example: 24710089) to show the current_stock in all locations. Show I should get some array/hash that allows me to output

Product 24710089 Location A: 10 Location C: 20 etc.

Ahh… I thought you wanted to be able to have stock at each location, and then have the total stock (which is what product.current_stock does right now). I’m going to go ahead and leave that alone, and show you another function that will do what you want (that way you can do either one)

class Product < ActiveRecord::Base has_many :mutations has_many :locations, :through => :mutations

def current_stock Mutation.find_all_by_product_id(self.id).inject(0) {|total, mut|

total += mut.mutation} end end

def location_stocks Mutation.find_all_by_product_id(self.id).each {|m| location_stock[m.location_id] = m.mutation} location_stock

end

Now let’s say you have two locations, location1 and location2. location1’s id = 14839, current stock = 24 location2’s id = 19248, current stock = 94 If each of those locations had product 24710089 in it, and you did

l = Product.find(24710089).location_stocks then l[14839] == 24 l[19248] == 94 Or, in Ruby parlance l == {14839 => 24, 19248 => 94}

Will that do what you want?

class Mutation < ActiveRecord::Base belongs_to :product belongs_to :location

def mutation mutation = 0 + self.buy - self.sell - self.transit - self.lost end end

class Location < ActiveRecord::Base

has_many :mutations has_many :products, :through => :mutations

You probably don’t want current_stock here, unless you want it to show the stock of all the products at this location

If you do, it’s: def current_stock Mutation.find_all_by_location_id(self.id).each {|m| product_stock[m.product_id] = m.mutation} product_stock end This will be product_stock == {24710089 => 24} for location1

and product_stock == {24710089 => 94} for location2