【问题标题】:Associate two already existing objects using Has And Belongs To Many使用 Has And Belongs To Many 关联两个已经存在的对象
【发布时间】:2024-01-21 13:42:01
【问题描述】:

我正在 Rails 中制作一个应用程序来展示动画,这些动画有并且属于多种语言,所以我创建了一个 HABTM 关联:

class Anime < ActiveRecord::Base
  has_and_belongs_to_many :languages
end

class Language < ActiveRecord::Base
  has_and_belongs_to_many :animes
end

现在我不知道如何在它们之间建立关联,我已经创建了许多语言的记录来使用它们,例如,ID 1 的语言是英语,ID 2 的语言是西班牙语,等等......我只想在动漫和语言之间建立关联,即,如果我想说 ID 为 1 的动漫仅提供西班牙语版本,那么我想在表animes_languages 中创建具有值anime_id: 1 的记录和language_id: 2 仅此而已,但我相信如果我执行命令Anime.find(1).languages.create 它不会使用现有的语言,它将创建一种新的语言,但我唯一想要的是在现有的动画之间建立关联使用已经存在的语言,那么,我该怎么做?我应该为animes_language的桌子制作模型吗?

这让我很困惑,因为当我按照此处enter link description here 的指定创建该表时,我创建的表没有 ID,它只有字段 anime_idlanguage_id

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 has-and-belongs-to-many


    【解决方案1】:

    为了安全起见,我会备份它。

    首先,您迁移表以删除与一个或另一个参考的现有关联(即,如果语言已经有许多动画等)。

    然后你需要创建一个迁移来创建关联表。

    rails g migration CreateJoinTableAnimeLanguage anime language
    

    那么你的模型中的关联指针应该可以正常工作了。

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

    当您想将一个与另一个已经存在的关联时:

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

    根据经验,建议不要尝试分步执行此操作。

    我会说找到创造最多的东西,我猜是Anime,然后找到一种方法来选择或创建一种语言:

    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
    

    【讨论】:

    • 很好,顺便说一句,我如何检查该关联是否已经存在?
    • 我很确定你不需要。如果它已经存在,您只需构建一个新的Anime 并引用某种语言id。否则,该语言将包含除 id 之外的所有内容并将被创建。
    • 我需要一些方法来知道 ID 为“x”的动漫是否已经与 ID 为“y”的语言相关联,或者我可能有多个记录anime_id = 'x' language_id = 'y' , 刚刚测试它并且可以发生。
    • 类似has_and_belongs_to_many :languages, uniq: true。请将我的回答标记为有用! x_X
    【解决方案2】:

    应该很简单

    anime = Anime.find(1)
    language = Language.find(1)
    anime.languages << language
    

    这将在两者之间创建连接记录

    【讨论】: