Still learning maintaining data with join tables

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

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

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

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/
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. :slight_smile: i recommend checking out his posts on the
topic, at 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 :wink:
reads of the documentation…

-Brian

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. :slight_smile: i recommend checking out his posts on the
topic, at 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

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

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