has_many :through best practices.

you forgot to write the answer? :slight_smile:

So I have to create deliveries as many as bags to delivery. If I select all bags together like: bags=Bag.all and I want to deliver these bags to user I have to create deliveries under a bags.each block?

I don't think you have previously said that you want one delivery to have many bags, is that what you want?

What are the relationships you have at the moment?

Do they meet your requirements?

Colin

So I have to create deliveries as many as bags to delivery. If I select all bags together like: bags=Bag.all and I want to deliver these bags to user I have to create deliveries under a bags.each block?

Correct, you need to create all the bags no matter what, so you'll want to loop through all the bags you want to create a delivery for and use the previously referenced code. If you're worried about the performance of doing a bunch of queries there are some gems that can help with that (http://www.continuousthinking.com/tags/arext is the one I always see, but I haven't used it) but I wouldn't bother unless you determine it’s a performance issue.

Also a note on your previous code:

user << bags

This won't work as its bad syntax: first you'd want user.bags since that's the collection you're adding to; and second << takes a single object and adds it to an array, where as you want to either replace the array (users.bags = bags) or concat another array (user.bags += bags). Also, from a performance perspective, I'm pretty sure either of those would do bags.length insert calls too (just like a .each loop would); in other words AR associations don't do any special bulk insert for you, it just hides the loops from you.

\Peter

Yes I've make a mistake, it is user.bags << bags.

At the moment I have :

class Ruser < ActiveRecord::Base has_many :deliveries has_many :bags, :through => :deliveries end

class Bag < ActiveRecord::Base has_many :deliveries has_many :rusers, :through => :deliveries end

class Delivery < ActiveRecord::Base belongs_to :ruser belongs_to :bag end

and Delivery has delivered_at as an extra attribute. I can delivery one or more bags to user and I want to know the date in which the bag or the bags is/are delivered. If I deliver, for example 3 bags in date 2011-01-01, I have to iterate over bags.each and do a user.deliveries.create(....) for every bag or there is better solution for that?

So I have to create deliveries as many as bags to delivery. If I select all bags together like: bags=Bag.all and I want to deliver these bags to user I have to create deliveries under a bags.each block?

I don't think you have previously said that you want one delivery to have many bags, is that what you want?

You have not answered this question and you snipped my other question, are the relationships correct for your requirement?

Please answer the first one and think about the second.

Colin

I've posted to have an opinion about it, that is if associations are correct.

So I have to create deliveries as many as bags to delivery. If I select all bags together like: bags=Bag.all and I want to deliver these bags to user I have to create deliveries under a bags.each block?

I don't think you have previously said that you want one delivery to have many bags, is that what you want?

You have not answered this question and you snipped my other question, are the relationships correct for your requirement?

I've posted to have an opinion about it, that is if associations are correct.

Sorry, that does not make sense. The question is whether a delivery relates to only one bag (so delivery belongs_to bag) or a delivery relates to many bags, in which case I imagine you want delivery has_many bags, bag belongs_to delivery.

Colin

If you have to solve this problem: you have 3 types of bags, wet type, dry type and type plastic. These bags must be delivered to an user and I need to know the date of delivery. It can be delivered bags of one kind or also bags of all three types. How do you create the associations? I think what I have done is correct.

Sorry, that does not make sense. The question is whether a delivery relates to only one bag (so delivery belongs_to bag) or a delivery relates to many bags, in which case I imagine you want delivery has_many bags, bag belongs_to delivery.

If you have to solve this problem: you have 3 types of bags, wet type, dry type and type plastic. These bags must be delivered to an user and I need to know the date of delivery. It can be delivered bags of one kind or also bags of all three types. How do you create the associations? I think what I have done is correct.

Does one delivery consist of a number of bags? Please answer yes or no.

Can a particular bag be in more than one delivery? Please answer yes or no.

Colin

Does one delivery consist of a number of bags? Please answer yes or no.

Yes.

Can a particular bag be in more than one delivery? Please answer yes or no.

Yes.

Does one delivery consist of a number of bags? Please answer yes or no.

Yes.

In which case Delivery belongs_to bag is not correct as this implies only one bag for each delivery.

Can a particular bag be in more than one delivery? Please answer yes or no.

Yes.

So a single bag can be in several deliveries? If so then you need has_and_belongs_to_many between deliveries and bags.

Colin

Then the associations are:

class Ruser < ActiveRecord::Base   has_and_belongs_to_many :deliveries

class Bag < ActiveRecord::Base   has_and_belongs_to_many :deliveries

class Delivery < ActiveRecord::Base   has_and_belongs_to_many :rusers   has_and_belongs_to_many :bags

mmm I don't like too much.

Does one delivery consist of a number of bags? Please answer yes or no.

Yes.

In which case Delivery belongs_to bag is not correct as this implies only one bag for each delivery.

Can a particular bag be in more than one delivery? Please answer yes or no.

Yes.

So a single bag can be in several deliveries? If so then you need has_and_belongs_to_many between deliveries and bags.

Then the associations are:

class Ruser < ActiveRecord::Base has_and_belongs_to_many :deliveries

class Bag < ActiveRecord::Base has_and_belongs_to_many :deliveries

class Delivery < ActiveRecord::Base has_and_belongs_to_many :rusers has_and_belongs_to_many :bags

That means that one delivery is to multiple users, is that what you want?

Colin

No, that’s too much habtm, the following is sufficient:

class Ruser < ActiveRecord::Base    has_many :deliveries

class Delivery < ActiveRecord::Base    belongs_to :ruser    has_and_belongs_to_many :bags

class Bag <ActiveRecord::Base    has_and_belongs_to_many :deliveries

or, if you want to give further attributes to your bag deliveries like count of bags per order, make it flat and explicit.

class Ruser < ActiveRecord::Base    has_many :deliveries

class Delivery < ActiveRecord::Base    belongs_to :ruser    has_many :bag_deliveries    has_many :bags, :through => :bag_deliveries

class BagDelivery < ActiveRecord::Base    belongs_to :delivery    belongs_to :bag    has_one :ruser, :through => :delivery

class Bags < ActiveRecord::Base    has_many :bag_deliveries    has_many :deliveries, :through => :bag_deliveries

– Matthias

Yes in a single day I can do a lot of deliveries to different users.

Colin meant that any single delivery is designed to be addressed to multiple users, and I doubt that this is what you want.

– Matthias

In date 2011-01-01 I can deliver bag type "plastic" to user1,user2 and user3 or in the same date I can deliver bag type "plastic", "wet" and "dry" to user1, user2 and user3, or I can do the same types of deliveries only to one user.

So is a delivery something like a truck load of bags, with some bags going to one user and other bags going to other users, all from the same delivery? If that is the case in which table are you proposing to save which bag(s) go to which user?

Colin