Проверка длины habtm ассоциации без сохранения

Позвольте мне начать путем включения источников - Прагматическое Поблочное тестирование в Java с JUnit (существует версия с C#-Nunit также.. но у меня есть этот.. его агностик по большей части. Рекомендуемый.)

Хорошие Тесты должны быть ПРОХОЖДЕНИЕ А (acronymn не является достаточно липким - у меня есть распечатка cheatsheet в книге, которую я должен был вытащить, чтобы удостовериться, что я разобрался в этом..)

  • Автоматический : Вызов тестов, а также проверка результатов для ПЕРЕДАЧИ/СБОЯ должен быть автоматический
  • Полный : Покрытие; Хотя ошибки имеют тенденцию кластеризироваться вокруг определенных регионов в коде, гарантировать, чтобы Вы протестировали все ключевые пути и сценарии.. Используйте инструменты, если Вы должны для знания непротестированных регионов
  • Повторяемый : Тесты должны привести к тем же результатам каждый раз.. каждый раз. Тесты не должны полагаться на неконтролируемые параметрические усилители.
  • Независимый : Очень важный.
    • Тесты должны тест только одна вещь за один раз. Несколько утверждений хорошо, пока они все тестируют одну функцию/поведение. Когда тест перестал работать, он должен точно определить местоположение проблемы.
    • Тесты не должны полагаться друг на друга - Изолированный. Никакие предположения о порядке выполнения теста. Гарантируйте 'чистый лист' перед каждым тестом при помощи установки/разрушения соответственно
  • Профессионал : В конечном счете у Вас будет столько же тестового кода сколько производство (если не больше), поэтому следуйте тому же стандарту хорошего дизайна для Вашего тестового кода. Хорошо учтенные классы методов с показывающими намерение именами, Никаким дублированием, тестами с хорошими именами, и т.д.

  • Хорошие тесты также работают Быстрый . любой тест, который принимает половину секунды для выполнения.. потребности, которые будут работаться на. Дольше набор тестов берет для выполнения.. менее часто это будет выполнено. Больше изменений dev попытается красться между выполнениями.. если что-нибудь повреждается.. займет больше времени выяснить, какое изменение было преступником.

Обновление 2010-08:

  • Читаемый : Это можно считать частью Профессионала - однако она не может быть подчеркнута достаточно. Испытание на кислотность должно было бы найти кого-то, кто не часть Вашей команды и того, чтобы просить, чтобы он выяснил поведение под тестом в течение нескольких минут. Тесты должны сохраняться точно так же, как производственный код - поэтому облегчите читать, даже если он прилагает больше усилий. Тесты должны быть симметричными (следуйте за шаблоном), и краткий (тестируют одно поведение за один раз). Используйте последовательное соглашение о присвоении имен (например, стиль TestDox). Постарайтесь не создавать помехи тесту "несущественными деталями".. станьте минималистом.

Кроме них, большинство других - инструкции, которые сокращают работу низкого преимущества: например, 'Не делают тестового кода, которым Вы не владеете' (например, сторонний DLLs). Не идите о тестировании методов get и методов set. Следите за отношением стоимости для преимущества или дефектной вероятностью.

5
задан EmFi 19 October 2009 в 21:46
поделиться

1 ответ

You had two problems here:

  1. You're overriding validations
  2. The order of operations in saving is causing problems.

You're overwriting the validate method which is a bad thing, because the built in behaviour to deny records with validation errors to be saved to the database. To add custom validations you want to do this:

validate :maximum_group_length

def maximum_group_length
    if self.groups.length > 5
        self.errors.add(:groups, "cannot have more than 5 groups")
    end
end

However, the nature of HABTM relationships requires you to do it as an after_save callback. Just because of the order that things are done. user.groups is based on the implicit join table and there for isn't updated until the join table is updated.

If you're trying to validate as part of a callback (before_save, after_creation, etc.), then adding an error to the object won't trigger a roll back. Callbacks will only trigger a rollback if they return false. This will handle the after save implementation the question suggest.

after_save :validate_maximum_group_length

def validate_maximum_group_length
    if self.groups.length > 5
        self.errors.add(:groups, "cannot have more than 5 groups")
        return false
    end
end

Another solution is to use an explicit join model. And a has_many :through relationship. The join model's table is updated in the update statement. Where as the has_many :through and HABTM relationships update the relationship after the save.

class User < ActiveRecord::Base
  has_many :user_groups
  has_many :groups, :through => user_groups, allow_destroy

  validate :max_group_length
    errors.add(:groups, "cannot have more than 5 groups") if self.user_groups.length > 5
  end

end

class UserGroup < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
end

HABTM implicitly uses a join table, so it doesn't need to be changed on the group side.

However you will need to modify your form to update the form to supply group_id in the params hash as params[:user][:user_group_attributes][0][:group_id][3]

11
ответ дан 13 December 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: