# Still learning maintaining data with join tables

**URL:** <https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953>\
**Category:** Rails\
**Created:** [April 16, 2006, 4:52am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953 "2006-04-16T04:52:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 16, 2006, 4:52am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/1 "2006-04-16T04:52:59Z")

</div>

Class Role  
has\_and\_belongs\_to\_many :users  
Class User  
has\_and\_belongs\_to\_many :roles  
Class RolesUsers  
has\_and\_belongs\_to\_many :roles  
has\_and\_belongs\_to\_many :users

According to the logs…I’m good through here

```
@roles_users = RolesUsers.find(:all,
  :conditions => ["user_id = ?", params[:users_id]] )

```

the next section of controller code is a problem…

```
for entry in @roles_users do
  entry.destroy
end

```

ActiveRecord::StatementInvalid in LoginController#save\_rights  
PGError: ERROR: relation “roles\_users\_users” does not exist

I really expected the above to work so I am missing some piece of  
fundamental understanding of how join tables work.

Anyone?

Thanks

Craig

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 16, 2006, 5:16am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/2 "2006-04-16T05:16:54Z")

</div>

Craig W. wrote:

> Class Role  
> has\_and\_belongs\_to\_many :users  
> Class User  
> has\_and\_belongs\_to\_many :roles  
> Class RolesUsers  
> has\_and\_belongs\_to\_many :roles  
> has\_and\_belongs\_to\_many :users

You seem to be mixing up has\_and\_belongs\_to\_many (join table) with  
has\_many :through (join model) associations. For habtm you don’t have a  
model class for the join table. If you need to manipulate the records in  
the join table or store additional attributes on them, then you need to  
switch to using has\_many :through. If so, you’ll need that model class,  
but then it is just another model and doesn’t need to be named the same  
way join tables do.

> the next section of controller code is a problem…
> 
> ```
> for entry in @roles_users do
> entry.destroy
> end
> 
> ```

Rails is confused because it’s trying to work with the join table  
records like they were model objects. I think you want to be iterating  
on roles, not roles\_users. If you want to remove an entry in the join  
table, do something like

some\_user.roles.delete(some\_role)

–  
Josh S.  
[http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 16, 2006, 5:32am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/3 "2006-04-16T05:32:24Z")

</div>

On Sun, 2006-04-16 at 05:16 +0200, Josh S. wrote:

> has\_many :through (join model) associations. For habtm you don’t have a  
> model class for the join table. If you need to manipulate the records in  
> the join table or store additional attributes on them, then you need to  
> switch to using has\_many :through. If so, you’ll need that model class,  
> but then it is just another model and doesn’t need to be named the same  
> way join tables do.

* * *

I need to manipulate the records in the join table.  
(i.e, delete/add because I can’t edit them since they don’t have an  
primary key)

What would be the proper structure for has\_many :through for the above  
setup?

(I’ll hold off on the delete stuff until I figure this out)

Thanks

Craig

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 16, 2006, 6:30am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/4 "2006-04-16T06:30:14Z")

</div>

On Apr 15, 2006, at 08:29 PM, Craig W. wrote:

> > You seem to be mixing up has\_and\_belongs\_to\_many (join table) with  
> > way join tables do.
> 
> * * *
> 
> I need to manipulate the records in the join table.  
> (i.e, delete/add because I can’t edit them since they don’t have an  
> primary key)

What you just said here, goes against the way Rails defines model  
associations. If the only thing you need to do is remove entries from  
a standard join table, you can do that with a standard habtm. Check  
out the habtm section on this page: \<[http://rails.rubyonrails.com/](http://rails.rubyonrails.com/)  
classes/ActiveRecord/Associations/ClassMethods.html#M000533\>. You’ll  
see how you can call both the delete method (for removing 1 or more  
joins) and the clear method (for removing all joins), between users  
and roles.

> What would be the proper structure for has\_many :through for the above  
> setup?

You would only use has\_many :through if your roles\_users table needed  
to have additional columns of data, beyond the two foreign keys. If  
this is the case, then you turn that join table into a “join model”,  
which would have a ID column, along with the two foreign keys, and  
whatever other columns you needed to keep track of data relative to  
the join entries. The URL that I put above also has the info for  
has\_many :through as does Josh’s Typo blog, since he’s kind of the  
“has\_many :through” guy. 🙂 i recommend checking out his posts on the  
topic, at [http://www.hasmanythrough.com/](http://www.hasmanythrough.com/).

This should also be a reminder to many posters out there, who might  
be struggling with this aspect of Rails/ActiveRecord. Make sure you  
take the time to learn how the various associations work and when you  
should use which type of association. They are extremely powerful,  
and as such, often difficult to grasp without 2 or 3 (or more 😉  
reads of the documentation…

-Brian

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 17, 2006, 3:56am UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/5 "2006-04-17T03:56:06Z")

</div>

On Sat, 2006-04-15 at 21:27 -0700, Brian V Hughes wrote:

> > > same  
> > > classes/ActiveRecord/Associations/ClassMethods.html#M000533\>. You’ll  
> > > which would have a ID column, along with the two foreign keys, and  
> > > whatever other columns you needed to keep track of data relative to  
> > > the join entries. The URL that I put above also has the info for  
> > > has\_many :through as does Josh’s Typo blog, since he’s kind of the  
> > > “has\_many :through” guy. 🙂 i recommend checking out his posts on the  
> > > topic, at [http://www.hasmanythrough.com/](http://www.hasmanythrough.com/).

* * *

OK - I refactored and got it all working today simply using the join  
tables but removing the ‘roles\_users.rb’ model

Life seemed to be good and I was able to get through all of the issues  
of editing/deleting/adding new records to the join table and they work.

I then committed my changes to the repository and updated my live system  
and find that I am now getting an error when using the join model in  
controller…

The error…

Processing LoginController#user\_rights (for 192.168.3.7 at 2006-04-16  
18:35:04) [GET]  
Session ID: 161d2b0f800a1069937f11381201e1b7  
Parameters: {“action”=\>“user\_rights”, “id”=\>“17”,  
“controller”=\>“login”}

NameError (uninitialized constant RolesUsers):  
/usr/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active\_support/dependencies.rb:100:in  
`const_missing' /usr/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/dependencies.rb:131:in `const\_missing’  
/usr/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active\_support/dependencies.rb:133:in  
`const_missing' /app/controllers/login_controller.rb:73:in `user\_rights’

Where the line 73 in question is…

```
@roles_users = RolesUsers.find(:all,
  :conditions => ["roles_users.user_id = ?", params[:id]],
  :order => 'role_id'
  )

```

and just for completeness…

Class Role has\_and\_belongs\_to\_many :users  
Class User has\_and\_belongs\_to\_many :roles

and there is a populated table (from migrations) called roles\_users  
which was populated in this fashion (in a migration)…

```
  User.find(:all).each { |u| u.roles << Role.find(:first,
    :conditions => ["id = ?", 3]) }

```

and the same ‘version’ works at home (though I am using Fedora 4 at home  
and RHEL 4 on the production system). Both have the same version of rake

- 0.7.1 and rails 1.1.2 and I have run ‘rake rails:update’ on both  
systems and I have verified that ‘role.rb’ and ‘user.rb’ are the same on  
both systems

Clues?

Craig

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 17, 2006, 1:53pm UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/6 "2006-04-17T13:53:34Z")

</div>

Craig W. wrote:

> > > > > has\_and\_belongs\_to\_many :users  
> > > > > same  
> > > > > see how you can call both the delete method (for removing 1 or more  
> > > > > the join entries. The URL that I put above also has the info for  
> > > > > I then committed my changes to the repository and updated my live system
> 
> ```
> :conditions => ["roles_users.user_id = ?", params[:id]],
> 
> User.find(:all).each { |u| u.roles << Role.find(:first,
> :conditions => ["id = ?", 3]) }
> 
> ```
> 
> and the same ‘version’ works at home (though I am using Fedora 4 at home  
> and RHEL 4 on the production system). Both have the same version of rake
> 
> - 0.7.1 and rails 1.1.2 and I have run ‘rake rails:update’ on both  
> systems and I have verified that ‘role.rb’ and ‘user.rb’ are the same on  
> both systems
> 
> Clues?

You said you had removed roles\_users.rb (implying that you are aiming  
for straightforward HABTM, rather than using a join model), so you  
shouldn’t be referring to RolesUsers in your controller.

To get the Roles for a given User you should just be able to use

@roles = @user.roles

(assuming that @user is the user with id params[:id])

If it isn’t breaking on your home system, you presumably haven’t removed  
roles\_users.rb from that.

regards

Justin

---

<div class="post-metadata">

**Author:** ![craigrails](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c2a13f/32.png) [@craigrails](https://www.ruby-forum.com/u/craigrails)\
**Post date:** [April 17, 2006, 5:02pm UTC](https://www.ruby-forum.com/t/still-learning-maintaining-data-with-join-tables/93953/7 "2006-04-17T17:02:03Z")

</div>

On Mon, 2006-04-17 at 12:50 +0100, Justin F. wrote:

> > > > > > has\_and\_belongs\_to\_many :roles  
> > > > > > but then it is just another model and doesn’t need to be named the  
> > > > > > classes/ActiveRecord/Associations/ClassMethods.html#M000533\>. You’ll  
> > > > > > whatever other columns you needed to keep track of data relative to
> > 
> > “controller”=\>“login”}  
> > @roles\_users = RolesUsers.find(:all,  
> > which was populated in this fashion (in a migration)…  
> > Clues?
> 
> If it isn’t breaking on your home system, you presumably haven’t removed  
> roles\_users.rb from that.

* * *

you are correct and I learned something about the nature of Rails…

I moved roles\_users.rb into RAILS\_ROOT/app/models/hold on my home system  
and didn’t add them to svn which is why it worked at home and not in  
production. Strange…anyway, copying them into production got me  
working which given the late hour of Sunday night and the prospect of  
them working tomorrow on new setup early this morning seemed to be a  
perfectly workable solution for the present and I can solve my riddle on  
my home system.

Thanks for the diagnosis - I thought it wouldn’t automatically find  
models hidden in a nested folder but indeed Rails does find them.

Craig
