2015-12-02 10 views
1

Я строит модель ActiveRecord для таблицы, которая хранит пары ключ/значениеИспользование Shoulda matchers для тестирования `allow_nil` в сочетании с` `uniqueness` и scope`

Пример -

|------------------------------| 
| KEY  | VALUE    | 
|----------|-------------------| 
| LOCATION | San Francisco, CA | 
| TITLE | Manager   | 
| LOCATION | New York City, NY | 
|------------------------------| 

Вот модель -

class CompanyEnum < ActiveRecord::Base 
    KEYS = [:title, :department, :location] 
    KEYS_ENUM = KEYS.map(&:to_s).map(&:upcase) 

    # `key` column must be one of the above - LOCATION, DEPARTMENT, or TITLE 
    validates(:key, inclusion: KEYS_ENUM, allow_nil: false) 

    # `value` can be anything, but must be unique for a given key (ignoring case) 
    validates(
    :value, 
    uniqueness: { scope: :key, case_sensitive: false }, 
    allow_nil: false 
) 
end 

Я использую shoulda matchers написать спецификации для этих проверок. Так что в моем файле спецификации у меня есть следующие две функции -

describe "validations" do 
    it { should_not allow_value(nil).for(:key) } 
    it { should_not allow_value(nil).for(:value) } 
end 

Моя проблема заключается в том, что первая проверка для :key проходов, но вторая проверка для :value терпит неудачу. В соответствии с определением модели оба используют один и тот же вариант allow_nil: false.

1) CompanyEnum validations value should not allow value to be set to nil 
    Failure/Error: it { should_not allow_value(nil).for(:value) } 
    Expected errors when value is set to nil, 
    got no errors 
    # ./spec/models/company_enum_spec.rb:13:in `block (4 levels) in <top (required)>' 
    # ./spec/support/analytics.rb:4:in `block (2 levels) in <top (required)>' 

Есть ли логическая проблема с использованием allow_nil: false с uniqueness: и scope: optoins? Или это связано с тем, что я называю фактические столбцы :key и :value (так как они кажутся достаточно родовыми, чтобы конфликтовать с некоторыми другими методами)?

Спасибо!

+0

Почему бы просто не использовать присутствие валидатор? Я думаю, что это беспорядок из-за положения сферы. Также упоминается только упоминание о производительности, но вы можете захотеть заморозить каждую строку и массив для перечисления ключей, иначе они будут созданы с каждым экземпляром модели. – CWitty

ответ

3

allow_nil: false по вашей проверке уникальности не означает, что nil не является допустимой величиной. Это немного вводит в заблуждение.

Как вы уже знаете, по умолчанию, проверка уникальности работает таким образом (судя по коду, который вы используете):

  • Если есть две записи с одинаковым значением key и value, то вторая запись должна быть недействительной по сравнению с первой (при условии, что первая существует в базе данных).
  • Если есть две записи с разными значениями key и value, тогда оба документа должны быть действительными.

И что же делает allow_nil? Давайте посмотрим, что the docs должен сказать:

:allow_nil - Если установлено в true, проскакивают эту проверку, если атрибут nil (по умолчанию false).

Так что, если верно, allow_nil позволяет две записи сосуществовать с nil значений для атрибута, проверяемого (в данном случае value).

Но вы указали allow_nil: false, что означает, что этот параметр не применяется в любом случае.

Таким образом, ваше первое использование allow_value не выполняется, потому что nil недействительное значение для key (проверка включения завершается с ошибкой).Второе использование, однако, связано с тем, что nil является допустимым значением для value (при отсутствии существующих записей, которые также имеют value от nil).

Моя точка, я думаю, что если вы действительно хотите проверить свои валидаций, вы должны использовать matchers, которые соответствуют непосредственно этим валидаций:

it do 
    should validate_inclusion_of(:key). 
    in_array(["TITLE", "DEPARTMENT", "LOCATION"]). 
    allow_nil 
end 

it do 
    should validate_uniqueness_of(:value). 
    scoped_to(:key). 
    case_insensitive 
end 
+0

Это имеет большой смысл, спасибо! Я предполагаю, что целью 'allow_nil' является не описание значения поля, но для отметки погоды сама проверка должна выполняться для значений« nil ». Кажется, вы немного обманчивы, как вы упомянули, но спасибо, что прояснили это – user2490003

 Смежные вопросы

  • Нет связанных вопросов^_^