HABTM重复记录

我有2个GameTheme模型,他们有一个has_and_belongs_to_many关联。 我已经尝试了许多解决方案来防止games_themes表中的重复记录,但没有解决方案可行。 问题是, games_themes是一个表,但它不是一个模型,所以我无法找到一种方法来有效地运行validation。

这是我试过的解决方案

 class Theme  true end class Game  true end 

您应该使用数据库级validation:

 #new_migration add_index :games_themes, [:game_id, :theme_id], :unique => true 

HABTM

这将阻止您在数据库中保存任何重复数据。 减轻Rails的负担并确保您只拥有游戏或主题。 问题是因为HABTM没有模型,没有可以在Rails中执行的validation,这意味着你需要使它成为db级别

正如评论中所提到的,这意味着您必须像这样处理从db引发的exception:

 #app/controllers/games_controller.rb def create #creation stuff here if @game.save #successful save else #capture errors end end 

使用:

 validates_uniqueness_of :theme_id, :scope => :game_id 

如下:

 class Theme < ActiveRecord::Base has_many :games, through: :games_themes end class Game < ActiveRecord::Base has_many :themes, through: :games_themes end class GamesThemes < ActiveRecord::Base belongs_to :game belongs_to :theme validates_uniqueness_of :theme_id, :scope => :game_id end 

要在连接表上运行validation,您应该使用has_many :through关联。 http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

创建新的模型GameTheme用于validation目的不是一个好主意。 我们可以在迁移中validation自己。

主题模型:

 class Theme < ActiveRecord::Base has_and_belongs_to_many :games, :association_foreign_key => 'theme_id', :class_name => 'Theme', :join_table => 'games_themes' end 

游戏模型:

 class Theme < ActiveRecord::Base has_and_belongs_to_many :games, :association_foreign_key => 'game_id', :class_name => 'Game', :join_table => 'games_themes' end 

games_themes migration:您可以为连接表添加唯一性,请查看此处了解更多详细信息。

 class GamesThemesTable < ActiveRecord::Migration def self.up create_table :games_themes, :id => false do |t| t.references :game t.references :theme end add_index :games_themes, [:theme_id, :game_id], :unique => true end def self.down drop_table :games_themes end end