Search code examples
ruby-on-railsruby-on-rails-4sqlite3-ruby

Deleting multiple objects in HABTM reference table


Im trying to destroy multiple records in my database table where :list column has the same name, however I get an error when I click on Destroy link: Could not find table 'bookmarks_posts', it says the error is in my controller line:

if @bookmarks.destroy_all

Why is it expecting a join table? How can I change that? Also I don't want to destory anything outside the given Bookmarks table. (I am using sqlite3, if that changes anything)

My table migration:

class CreateBookmarks < ActiveRecord::Migration
  def change
    create_table :bookmarks do |t|
      t.string :list
      t.references :user, index: true, foreign_key: true
      t.references :post, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

My controller - destroy and show:

  def destroy
    @list = Bookmark.find(params[:id])
    @bookmarks = Bookmark.where(:list => @list.list)

    if @bookmarks.destroy_all
        redirect_to bookmarks_url
    end
  end

  def show
    @lists = Bookmark.where(user_id: current_user.id).where(post_id: nil)
    @list = Bookmark.find(params[:id])
    @bookmarks = Bookmark.where.not(post_id: nil).where(list: @list.list)
    @posts = Post.where(:id => @bookmarks.map(&:post_id))
  end

in my show view I use this:

<%= link_to 'Destroy', @list, method: :delete %>

My models:

class Bookmark < ActiveRecord::Base
  has_and_belongs_to_many :users
  has_and_belongs_to_many :posts
end

Solution

  • "Why is it expecting a join table?"

    Because you have specified a HABTM association between Bookmark and Post models. So when you delete a Bookmark or a Post, it wants to remove any rows in the join table that are referencing the deleted item's ID.

    The problem seems to be that you're either specifying the wrong association type in your models, or you've created the wrong migration to support a HABTM association.

    For discussion, let's assume your database migration above is correct, eg: you want to store a user_id and post_id in the Bookmarks table. This means that you would have the following associations:

    class Bookmark < ActiveRecord::Base
      belongs_to :user
      belongs_to :post
    end
    
    class User < ActiveRecord::Base
      has_many :bookmarks
    end
    
    class Post < ActiveRecord::Base
      has_many :bookmarks
    end
    

    If you actually need a HABTM relationship, then you need to do a migration that creates a join table.

    One way to figure out what the type of association you need is to remember that if a table has the ID of another model (eg: Bookmarks table has a user_id column), then that is a belongs_to association.