Orphan habtm rows

HI,

i use models User and Groups connected with many to many association, so
i have users table, groups and groups_users.

lets say i create one user and one group. next i add a group to user. so
now my table groups_users has one entry i.e.

group_id | user_id
_|
1 | 1

ok, when i delete both my group and user, above entry is not deleted,
thus leaving alone without any reason… its just an orphan record, which
is useless.

is there any parameter in rails that removes such records ?
i dont want to have too many useless records at all.

btw. its not :dependant => :destroy parameter, this applies only to
has_many association…

regards.

Piotr N. wrote:

group_id | user_id
_|
1 | 1

btw. its not :dependant => :destroy parameter, this applies only to
has_many association…

I know, that it is not directly an answer to your current problem. But
perhaps you should change your HABTM to a “has_many :through”
relationship

Like this:

  1. Change above table from “users_groups” to “memberships” and add an
    auto-incremented id field (of course as primary key)

  2. Create a new model Membership with these declarations:

belongs_to :user
belongs_to :group

  1. in your Group model, replace the HABTM declaration with this:

has_many :memberships, :dependent => :destroy
has_many :users, :through => :membership

  1. ditto in the User model:

has_many :memberships, :dependent => :destroy
has_many :groups, :through => :membership

You ought to be able to do this on your existing database and
application without changing any other program lines. The access to the
associated data are the same. And the :dependant declaration will take
care of future orphans.

Hope this helps.

  • Carsten

Piotr N. wrote:

btw. i wonder why something simple isnt done with regular habtm
relationship…

I can’t remember when the :dependent keyword was added to ActiveRecord,
but I know, that ever since Rails 1.2, “has_many :trough” has been
favored by the Rails core team over HABTM.

BTW: “has_many :through” has another advantage over HABTM: In your
“memberships” table, you are allowed to add attributes e.g. like this

memberships

id (int)
user_id (int)
group_id (int)
valid_from (datetime)
valid_to (datetime)

and access these from your model code.

anyway, thanks a lot Carsten :slight_smile:
have a nice day (evening)

You are very welcome, I am (unfortunately) not often on the Ruby-forum,
but it gives me pleasure when I’m able to help others in need. :slight_smile:

You have a nice evening too.

  • Carsten

Carsten G. pisze:

“memberships” table, you are allowed to add attributes e.g. like this

anyway, thanks a lot Carsten :slight_smile:
have a nice day (evening)

You are very welcome, I am (unfortunately) not often on the Ruby-forum,
but it gives me pleasure when I’m able to help others in need. :slight_smile:

You have a nice evening too.

  • Carsten

ok ive done this, but when i do
usr = User.find(:first)
usr.groups

i get error:

ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the
associa
tion :membership in model User

my models and tables are as follows

class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :membership
end

class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
end

class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :users, :through => :membership
end

excerpt form my schema.rb:

create_table “memberships”, :force => true do |t|
t.column “group_id”, :integer
t.column “user_id”, :integer
end

any ideas ?

ok, figured it out :slight_smile:

class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :membership
end

class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :users, :through => :membership
end

should be:

class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :memberships
end

class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :users, :through => :memberships
end

In overall the through attribute value should be pluralized :slight_smile:

big thank you

Piotr N. pisze:

end
has_many :memberships, :dependent => :destroy

well, although it works, it doesnt resolve my problem
when i delete user or group, the membership item (containng both those
user and group) is not deleted…

wonder why…

Piotr N. pisze:

has_many :users, :through => :membership

class Group < ActiveRecord::Base

well, although it works, it doesnt resolve my problem
when i delete user or group, the membership item (containng both those
user and group) is not deleted…

wonder why…

just noticed that it works only when i do destroy method on my user or
group instead of delete…

Piotr N. wrote:

should be:

class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :memberships

Sorry, a typo from me…

Sometimes i just hate David for doing the pluralization thing… :wink:

David hvis du læser dette, så: Puha! Slemme dreng! :slight_smile:

(just a little rambling in Danish - I’m from Denmark as well)

  • Carsten

Piotr N. wrote:

just noticed that it works only when i do destroy method on my user or
group instead of delete…

From the API description of ActiveRecord:

delete(id)
Deletes the record with the given id without instantiating an object
first. If an array of ids is provided, all of them are deleted.

destroy(id)
Destroys the record with the given id by instantiating the object and
calling destroy (all the callbacks are the triggered). If an array of
ids is provided, all of them are destroyed.

The essential here is that delete(id) “deletes without instantiating an
object first”. Which really boils down to a SQL like “delete from users
where id = NN limit 1”

delete() does not instantiate the object, therefore it knows nothing of
any associations/relationships.

Always use destroy() if possible.

  • Carsten

Carsten G. pisze:

perhaps you should change your HABTM to a “has_many :through”
belongs_to :user
has_many :memberships, :dependent => :destroy

  • Carsten
    quite interesting, ill see if that works for me.
    btw. i wonder why something simple isnt done with regular habtm
    relationship…

anyway, thanks a lot Carsten :slight_smile:
have a nice day (evening)

Always use destroy() if possible.

  • Carsten

i will, rails rocks !

i ve just switched from java/.net to rails and im so excited so far :slight_smile:

greets.

Piotr N. wrote:

i will, rails rocks !

i ve just switched from java/.net to rails and im so excited so far :slight_smile:

Have you seen these?

http://www.railsenvy.com/tags/Commercials

Start with the ones in the bottom - they are fun and - IMHO quite
accurate :slight_smile:

Been at a few of the langauges/frameworks myself earlier. Now I only do
PHP and Rails - and PHP only because I have so many existing
customers/solutions that I would hate to rewrite.

But you’ve made a good choice - you won’t regret it!

  • Carsten

Carsten G. pisze:

Start with the ones in the bottom - they are fun and - IMHO quite
accurate :slight_smile:

Been at a few of the langauges/frameworks myself earlier. Now I only do
PHP and Rails - and PHP only because I have so many existing
customers/solutions that I would hate to rewrite.

But you’ve made a good choice - you won’t regret it!

  • Carsten
    yes, ive seen them all, pretty funny, especially rails vs .net #2 :slight_smile:
    starting 2 projects now in rails, im quite excited :slight_smile:

greets.