Search code examples
ruby-on-railsactiverecordforeign-keysrails-activerecordhas-and-belongs-to-many

HABTM: can't create a resource


Following this tutorial I'm trying to create a many to many between search and listing models.

When everything is set, I can't create a new search. Here's the error I get:

irb(main):001:0> Search.create(term: "baby")
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
Traceback (most recent call last):
        1: from (irb):1
NoMethodError (undefined method `listing_id' for #<Search id: nil, term: "baby", created_at: nil, updated_at: nil>
Did you mean?  listing_ids
               listing_ids=
               listings
               listings=)

Here's my migrations:

class CreateJoinTableSearchesListings < ActiveRecord::Migration[5.1]
    def change
        create_join_table :searches, :listings do |t|
          t.index [:search_id, :listing_id]
          t.index [:listing_id, :search_id]
        end
    end
end

class CreateSearches < ActiveRecord::Migration[5.1]
    def change
        create_table :searches do |t|
          t.string :term, index: true

          t.timestamps
        end
    end
end

class CreateListings < ActiveRecord::Migration[5.1]
    def change
        create_table :listings do |t|
          ...
          t.string :title
          t.integer :listing_id
          ...

          t.timestamps
        end
    end
end

Here's my models:

class Search < ApplicationRecord
  has_and_belongs_to_many :listings, optional: true

  validates :listing_id, uniqueness: true
end

class Listing < ApplicationRecord
  has_and_belongs_to_many :searches, optional: true
  belongs_to :shop, optional: true

  validates :listing_id, uniqueness: true
end

I tried this a few moments ago and it worked perfectly. Then I rolled back with STEP=2 in order to add to the Searches migration an index on "term", not working since :(

Thanks in advance!


Solution

  • HABTM does not require to keep one model id inside another. In your case

    Search model no need to have listing_id and Listing model no need to have search_id.

    We'll be having a join table(SearchesListings) for this.

    Remove validates: listing_id, uniqueness: true from models as well as the database.

    then it works.