atallest
atallest

Reputation: 97

Deleting an active record entry from a joined table without deleting the orginal

I am working on a web application written in ruby on rails

There is a model of courses that exists in the database. A user has the ability to save courses that he/she plans to take. I accomplish this by having a current_user.courses table. (courses_users)

However, if a user wishes to remove a saved course, and I issue a delete request with that id like so

current_user.courses.find_by(id: params[:id]).destroy

I end up deleting both the entry in the joined table and the entry in the courses table. I confirmed this by looking at the server logs and found

DELETE FROM `courses_users` WHERE `courses_users`.`course_id` = 219
SQL (0.4ms)  DELETE FROM `courses` WHERE `courses`.`id` = 219

Doing the two actions described above when I only want the first.

Is there a way to just remove just the entry in the joined table? Or does that go against the nature of a joined table? If so, is there a more efficient way of achieving this functionality?

Any help would be appreciated and if you would have me post anything else please ask.

Thank you,

EDIT: The relationships between the two models:

a user has_and_belongs_to_many courses

and a course has_and_belongs_to_many users

Upvotes: 1

Views: 1672

Answers (2)

joelparkerhenderson
joelparkerhenderson

Reputation: 35453

Your code is saying to destroy the course, so that's what ActiveRecord is doing.

You want to delete the association, not destroy the user nor the course.

The solution is to use collection.delete(object, …)

  • This removes each object from the collection by deleting the association from the join table.

  • This does not destroy the objects.

Example code:

def delete_user_course_association(user_id, course_id)
  user = User.find(user_id)
  course = user.courses.find(course_id)
  user.courses.delete(course) if course 
end

See Rails API ActiveRecord Associations has_and_belongs_to_many

Upvotes: 2

roob
roob

Reputation: 1136

The line below deletes the courses record with id params[:id]

current_user.courses.find_by(id: params[:id]).destroy

I think you meant to do:

  current_user.courses.delete( params[:id] )

Upvotes: 2

Related Questions