Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-4has-and-belongs-to-many

Associate two already existing objects using Has And Belongs To Many


I'm making an App in Rails to show anime, these animes has and belongs to many languages, so I made a HABTM association:

class Anime < ActiveRecord::Base
  has_and_belongs_to_many :languages
end

class Language < ActiveRecord::Base
  has_and_belongs_to_many :animes
end

Now I don't know how can I make associations between them, I've created many Languages' records to use them, for example, Language with ID 1 is English, Language with ID 2 is Spanish, etc... And I want to just make the associations between an anime and a language, ie, if I want to say that the Anime with ID 1 it's available in Spanish only, then in the table animes_languages I want to create the record with values anime_id: 1 and language_id: 2 and nothing more, but I belive that if I execute the command Anime.find(1).languages.create it will not use an already existing language, it will create a new language, but the only thing I want is to make associations between already existing animes with already existing languages, so, How can I do this? Should I make a model for the table animes_language?

It's confusing for me cause when I created that table as specified here enter link description here, I created the table without ID, it only have the fields anime_id and language_id.


Solution

  • Just to be safe I will back it up.

    First you migrate your tables to remove already existing association to one or the other reference (i.e. if language already have many animes, etc).

    Then you need to create a migration to create the associative table.

    rails g migration CreateJoinTableAnimeLanguage anime language
    

    Then the association pointers in your models should work properly.

    class Anime < ActiveRecord::Base
      has_and_belongs_to_many :languages
    end
    
    class Language < ActiveRecord::Base
      has_and_belongs_to_many :animes
    end
    

    At which point whenever you want to associate one to the other already existing:

    Anime.find(1).languages << Language.find(1)
    

    Experience would recommend against trying to do this in seperate steps.

    I'd say find what gets created the most, I'd guess Anime, then find a way to choose or create a language using:

    class AnimeController < ApplicationController
      def create
        @anime = Anime.new(anime_params)
        @success = @anime.save
      end
    
      private
        def anime_params
          params.require(:anime).permit(:stuff, :languages => [:id, :or_stuff])
        end
    end