HABTM duplicate records

后端 未结 4 665
醉梦人生
醉梦人生 2020-12-30 13:18

I have a 2 models Game & Theme and they have a has_and_belongs_to_many association. I have tried many solutions to prevent duplicate records in

相关标签:
4条回答
  • 2020-12-30 13:57

    Use:

    validates_uniqueness_of :theme_id, :scope => :game_id
    

    As follows:

    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
    
    0 讨论(0)
  • 2020-12-30 14:07

    You should use database-level validation:

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

    HABTM

    This will prevent you saving any duplicate data in the database. Takes the burden off Rails & ensures you only have game or theme. The problem is because HABTM doesn't have a model, there's no validation you can perform in Rails, meaning you need to make it db-level

    As mentioned in the comments, this means you'll have to handle the exceptions raised from the db like this:

    #app/controllers/games_controller.rb
    def create
        #creation stuff here
        if @game.save
            #successful save
        else
            #capture errors
        end
    end
    
    0 讨论(0)
  • 2020-12-30 14:10

    To run validations on join table you should use has_many :through association instead. http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

    0 讨论(0)
  • 2020-12-30 14:16

    Creating new Model GameTheme for validation purpose is not a good idea. We can validate itself in migration.

    Theme Model:

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

    Game Model:

    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: You can add uniqueness to join table, Have a look here for more detail.

    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
    
    0 讨论(0)
提交回复
热议问题