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