Has through

Hi,

I have 3 models

Product
has_many :mutations

def current_stock

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 ?

On 2/23/07, bitterbal [email protected] wrote:

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

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 ?

On 2/25/07, bitterbal [email protected] wrote:

      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

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

end

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

class Location < ActiveRecord::Base