HABTM重复记录
我有2个Game
和Theme
模型,他们有一个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