Topic: [SOLVED] Scopes and Many-to-Many checking

I have the following many to many relationship (using a relationships table).

#Eraser.rb
has_and_belongs_to_many :pockets

#Pencil.rb
has_and_belongs_to_many :pockets

#Pocket.rb
has_many :pencils
has_many :erasers

And of course I have my erasers_pencils table in the DB that links them together.

Now, when creating a "Pocket", you're able to select from a list of pencils and erasers. However, I would like to limit the list of pencils/erasers to only those that are "available" (not already assigned to a pencil/eraser).

I know that I'll need to add a scope to the pencil/eraser model, but how would I do this?

scope :available, where()

I need to make sure the pencils do not have an eraser assigned, and vice-versa.

Thanks!

Last edited by wesf90 (2012-02-17 21:30:06)

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

I think you need TWO scopes

One for pencils that have no pockets

One for erasers that have no pockets

Since you said vice-versa?

Is that correct?

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

Yeah, I'll need to do the scopes for both pencils AND erasers. My question is, what would I put in the "where" of the scope? How could I check if the eraser/pencil is already related to their counterpart?

Last edited by wesf90 (2012-02-16 21:55:34)

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

First, I'm confused, would not your relationships look like:

#Eraser.rb
has_many :pencils, :through => :eraser_pencils

#Pencil.rb
has_many :erasers, :through => :eraser_pencils

????

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

Sorry, wow, I really messed up there. What I meant to write in my original post was

#Eraser.rb
has_and_belongs_to_many :pockets

#Pencil.rb
has_and_belongs_to_many :pockets

#Pocket.rb
has_many :pencils
has_many :erasers

Sorry for that Brad. I've edited my original post to reflect the changes

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

But you SHOULD change it!  It's the rails convention!

Makes life much easier!

Change Pockets.rb to EraserPencils.rb

That way the rails magic can happen!!!!

You don't HAVE to change it,  but it will just make more work for you!

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

Very interesting! However, I don't think this would work in my situation because Pocket is also serving as a "middle-man" for other models as well. So renaming "Pocket.rb" to "EracerPencil.rb" would cause it to only work with the Pencil/Eraser models, correct?

Thanks

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

You are correct, BUT!

You could change it from has_and_belongs_to_many to has_many, :through

Then you could do this:
#Eraser.rb
has_many :pencils, :through=> :pockets

#Pencil.rb
has_many :erasers, :through => :pockets

Then you are freed up a bit,  so long as pockets has attributes :pencil_id, and :eraser_id, these will work

@pencils = Eracers.pencils
@erasers = Pencils.erasers

But now you are free to use the pockets table for other things. i.e.  you could add pocket_protectors!  Add a pocket_protectors_id attribute to pockets,  then you can do

#PocketProtector.rb
has_many :pencils, :through => :pockets

Then you could do

@pocket_protectors = @pencils.pocket_protectots

has_and_belongs_to_many is more restrictive,  has_many, :through opens things up for more creative use of the intermediate join table.

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

Handy! smile

However, the pencils and erasers can belong to several pockets. So Pocket 1 can have Eraser 1, Eraser 2 and Pencil 2. See what I'm saying? So the "Pocket" cannot have DB fields for "pencil_id" and "eraser_id" because there can be more than 1 pencil/eraser assigned to the pocket.

So has_and_belongs_to_many along with a join table is the best way to go in this situation, correct? Your answers are teaching me much more than what I'm asking, which is a good thing!

Thanks

Last edited by wesf90 (2012-02-17 11:02:32)

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

has_an_belongs_to_many is a join table, just a simple one with two ids

I think what you want is two (or more) has_and_belongs_to_many's?

#Eraser.rb
has_and_belongs_to_many :pockets
#Pencil.rb
has_and_belongs_to_many :pockets

with HABTM as above,  you'd have to set up two join table

eraser_pockets
  pocket_id
  eraser_id
pencil_pockets
  pocket_id
  pencil_id

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

Wow, why are my problems so simple? Thanks!

I have one other question about scopes real quick before I mark this thread as "Solved". I hope you can help with this as well.

Using the same analogy with pockets, here's my situation: 1 Shirt has 1 Pocket. I have setup the relations in the models to reflect what I'm needing. This works fine (just a simple Pocket belongs_to Shirt).

My questions now is, when creating a new "Pocket", I have a dropdown menu to select a single Shirt, however, if a shirt is already assigned to a Pocket, then I do not want the shirts to appear in the dropdown list. So, I'm needing an :available scope for my Shirts model. How would I do this?

# Shirt.rb
scope :available, where('There arent any pockets assigned to this shirt')

The Pocket table has the shirt_id field. So how would I check that from the shirt model? Or am I going about this all wrong?
Thanks!

Last edited by wesf90 (2012-02-17 11:52:45)

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!

Re: [SOLVED] Scopes and Many-to-Many checking

scope :available, joins("left outer join pockets on shirts.id = pockets.shirt_id").where("pockets.shirt_id is null")

I think that's right,  but the key thing is you want a LEFT OUTER JOIN

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: [SOLVED] Scopes and Many-to-Many checking

That worked. I wasn't sure how to use joins in rails, you're a big help. Thanks

Remember to edit your topic title and add "[SOLVED]" if your question has been answered!

Follow me!