Ruby on rails 具有多个、属于关联和STI的模型的ActiveRecord验证

Ruby on rails 具有多个、属于关联和STI的模型的ActiveRecord验证,ruby-on-rails,validation,activerecord,single-table-inheritance,Ruby On Rails,Validation,Activerecord,Single Table Inheritance,我有四种型号: 使用者 奖励 徽章 游戏周 这些协会如下: 用户有很多奖项 奖励属于用户 徽章有很多奖项 该奖项属于徽章 用户有许多游戏周 游戏周属于用户 《游戏周刊》有很多奖项 该奖项属于本周比赛 因此,用户id、徽章id和游戏周id是奖励表中的外键 Badge实现了一个STI模型。假设它有以下子类:BadgeA和BadgeB 需要注意的一些规则: 比赛周id fk对于BadgeA可以为零,但是对于BadgeB不能为零 以下是我的问题: 对于BadgeA,如何编写只能授予一次的验证?也

我有四种型号:

  • 使用者
  • 奖励
  • 徽章
  • 游戏周
这些协会如下:

  • 用户有很多奖项
  • 奖励属于用户
  • 徽章有很多奖项
  • 该奖项属于徽章
  • 用户有许多游戏周
  • 游戏周属于用户
  • 《游戏周刊》有很多奖项
  • 该奖项属于本周比赛
因此,用户id、徽章id和游戏周id是奖励表中的外键

Badge实现了一个STI模型。假设它有以下子类:BadgeA和BadgeB

需要注意的一些规则:

比赛周id fk对于BadgeA可以为零,但是对于BadgeB不能为零

以下是我的问题:

  • 对于BadgeA,如何编写只能授予一次的验证?也就是说,用户不能有多个——永远不能
  • 对于BadgeB,我如何编写一个每游戏周只能授予一次的验证

  • 数据模型:

    据我理解,这是您的数据模型(单击放大):

    迁移:

    迁移将使您在迁移级别满足第二个要求:

    class CreateAwards < ActiveRecord::Migration
      def self.up
        create_table :awards do |t|
          # custom attributes here
          t.string     :name
          t.text       :description
          t.references :user,       :null => false
          t.references :game_week#,  :null => false
          t.references :badge,      :null => false
          t.timestamps
        end
        # a user can be awarded no more than a badge per week
        add_index :awards, [:user_id, :badge_id, :game_week_id], :unique => true
        # a user can be awarded no more than a badge for ever
        #add_index :awards, [:user_id, :badge_id], :unique => true
      end
    
      def self.down
        drop_table :awards
      end
    end
    
    class CreateAwardsfalse
    t、 参考:game_week#,:null=>false
    t、 参考:badge,:null=>false
    t、 时间戳
    结束
    #用户每周最多可获得一枚徽章
    添加\索引:奖励,[:用户\ id,:徽章\ id,:游戏\周\ id],:唯一=>true
    #用户最多只能获得一枚徽章
    #添加索引:奖励,[:用户id,:徽章id],:唯一=>true
    结束
    def自动关闭
    下表:奖项
    结束
    结束
    
    型号:

    该模型将让您在模型级别满足两个需求:

    class Award < ActiveRecord::Base
      validate_uniqueness_of :user, :badge,
        :if => Proc.new { |award| award.badge === BadgeA }
      validate_uniqueness_of :user, :badge, game_week,
        :unless => Proc.new { |award| award.badge === BadgeA }
      #validate_uniqueness_of :user, :badge, game_week,
      #  :if => Proc.new { |award| award.badge === BadgeB }
    end
    
    班级奖励Proc.new{| award | award.badge===BadgeA}
    验证用户、徽章、游戏周的唯一性,
    :除非=>Proc.new{| award | award.badge===BadgeA}
    #验证用户、徽章、游戏周的唯一性,
    #:if=>Proc.new{| award | award.badge===BadgeB}
    结束
    
    注意:


    我没有尝试这些代码片段,但我认为这里的想法是:)

    这是Ruby中的case equality操作符。您可以在[Object Ruby doc][1]和[blog post][2]中看到更多详细信息。[1]: [2]: