Подтверждения ActiveRecord для моделей с has_many, принадлежащим для ассоциаций и STI - PullRequest
3 голосов
/ 25 мая 2010

У меня есть четыре модели:

  • Пользователь
  • Премия
  • Значок
  • GameWeek

Ассоциации заключаются в следующем:

  • У пользователя много наград.
  • Премия принадлежит пользователю.
  • Знак имеет много наград.
  • Награда принадлежит значку.
  • У пользователя много игровых недель.
  • GameWeek принадлежит пользователю.
  • GameWeek имеет много наград.
  • Награда принадлежит game_week.

Таким образом, user_id, badge_id и game_week_id являются внешними ключами в таблице наград.

Знак реализует модель ИППП. Скажем так, у него есть следующие подклассы: BadgeA и BadgeB.

Некоторые правила, на которые следует обратить внимание:

game_week_id fk может быть ноль для BadgeA, но не может быть ноль для BadgeB.

Вот мои вопросы:

  1. Для BadgeA, как мне написать подтверждение, что оно может быть присуждено только один раз? То есть пользователь не может иметь больше одного - когда-либо.
  2. Для BadgeB, как мне написать подтверждение, что оно может быть присуждено только один раз за игровую неделю?

1 Ответ

1 голос
/ 27 мая 2010

Модель данных:

В моем понимании, вот ваша модель данных (нажмите, чтобы увеличить):

Модель данных http://yuml.me/6afcad62

Migration:

Миграция позволит вам выполнить ваше второе требование на уровне миграции:

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 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

Примечание:

Я не пробовал эти фрагменты, но я думаю, что идея здесь:)

...