Has_many :through best practices

On 25 January 2011 17:32, Peter [email protected] wrote:

Then I can do user.deliveries.where(:delivered_at =>
d1 = user.deliveries.create(:bag => bag1, :delivered_at => Time.now)
user.deliveries # => [d1]
user.bags # => [bag1] - Performs the query, finds the bag
through the delivery, caches it
d2 = user.deliveries.create(:bag => bag2, :delivered_at => 1.day.ago)
user.deliveries # => [d1, d2] - Using the association to create made
it know about the new one
user.bags # => [bag1] - Still cached from above
user.bags.reload # => [bag1, bag2] - Forces it to rerun the query

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?

On 24 January 2011 18:06, [email protected] [email protected]
wrote:

As Colin mentions though, you’re probably best using user.deliveries
<<, as that will both set your association IDs correctly, and have the
collection all happy.

About this point I’m still confused.
I want delivery one or more bags to ruser and I want to set the date
of delivery.
I’m thinking:
user=Ruser.first;
bags=Bag.all
user << bags,
this create deliveries but set delivered_at == nil.
Then I can do user.deliveries.where(:delivered_at =>
nil).update_all(:delivered_at => Date.today).
Can it be a solution?

On Jan 25, 11:01am, Mauro [email protected] wrote:

On 25 January 2011 17:32, Peter [email protected] wrote:

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 its 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

On 25 January 2011 18:10, Peter [email protected] wrote:

want to loop through all the bags you want to create a delivery for
This won’t work as its bad syntax:
Yes I’ve make a mistake, it is user.bags << bags.

On 25 January 2011 17:01, Mauro [email protected] wrote:

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

On 25 January 2011 18:10, Colin L. [email protected] wrote:

What are the relationships you have at the moment?

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?

On 25 January 2011 18:35, Colin L. [email protected] wrote:

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.

On 25 January 2011 17:17, Mauro [email protected] wrote:

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

On 25 January 2011 21:23, Colin L. [email protected] wrote:

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.

On 25 January 2011 22:15, Mauro [email protected] wrote:

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

On 26 January 2011 08:53, Colin L. [email protected] wrote:

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.

On 26 January 2011 08:00, Mauro [email protected] wrote:

On 26 January 2011 08:53, Colin L. [email protected] wrote:

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

On 25 January 2011 17:55, Mauro [email protected] wrote:

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

On 26 January 2011 10:10, Mauro [email protected] wrote:

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

On 26 January 2011 09:16, Colin L. [email protected] wrote:

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

mmm I don’t like too much.

On 26.01.2011 11:10, Mauro wrote:

has_and_belongs_to_many :bags

mmm I don’t like too much.

No, thats 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

On 26 January 2011 11:58, Colin L. [email protected] wrote:

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?

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

On 26.01.2011 13:20, Mauro wrote:

On 26 January 2011 11:58, Colin L.[email protected] wrote:

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

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

On 26 January 2011 13:12, Mauro [email protected] wrote:

users, and I doubt that this is what you want.

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

On 26 January 2011 14:42, Colin L. [email protected] wrote:

Colin meant that any single delivery is designed to be addressed to multiple
to save which bag(s) go to which user?
We are confusing and it 's my fault because of my poor English.
Back to the top.
I have a lot of users and I have three bag types: “plastic”, “wet” and
“dry”.
At date 2011-01-01 a user comes to me and I must deliver to him some
bags of type “plastic”, I give bags to him I must annotate the date of
deliver and what type of bags I gave.
Not matter the number of bags.
At the same date another user comes to me and I must give to him some
bags of type “plastic” and “wet”, I give the bags I must annotate the
date of deliver and what type of bags I gave.
Then comes another user and I must give bags of type “dry”, then comes
another user and I must give bags of all three types.
At date 2011-01-02 it can be the same story, and so on.
At the end I must know for every user how much deliveries, the dates
of every single delivery and for every single delivery what type of
bags I gave to him.