Проверка модели с «преднамеренно» неверными данными

Источник данных, с которым я работаю, ужасен. В некоторых местах, где вы ожидаете целые числа, вы получаете «Три». В поле «Номер телефона» может появиться «номер телефона — xxx». Некоторые поля просто пусты.

Это нормально, так как я анализирую каждое поле, так что «Три» в моей модели окажется целым числом 3, телефонные номера (и тому подобное) будут извлечены с помощью регулярного выражения. Пользователи сервиса ЗНАЮТ, что данные отрывочны и неполны, поскольку это досадный факт того, как поддерживается наш источник данных, и мы ничего не можем с этим поделать, кроме как активизировать нашу игру по анализу! Кроме того, мы медленно создаем собственную версию данных по мере того, как анализируем все больше и больше исходных данных, но пока этого бедного источника достаточно.

Таким образом, пользователи выбирают данные, которые они хотят проанализировать, а мы делаем все возможное, возвращая неполную/неправильную модель. Теперь окончательная модель, которую мы хотим сохранить, должна быть проверена — есть определенные поля, которые не могут быть нулевыми, определенные строки должны соответствовать формату и так далее.

Поток приложения:

  1. Пользователь сообщает сервису, какие данные анализировать.
  2. Сервис отключается и собирает данные, анализирует все, что может, и возвращает частичную модель с любыми данными, которые он может получить.
  3. Мы отображаем данные для пользователя, позволяя ему вносить исправления и заполнять любые обязательные поля, для которых данные не были собраны.
  4. Эти скорректированные пользователем данные должны быть сохранены и, следовательно, проверены.
  5. Если проверка не пройдена, снова покажите данные, чтобы пользователь мог внести исправления, смыть и повторить.

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

  1. 2 модели - модель данных с проверками и т. д. и модель UnconfirmedData без проверок. Исходные данные помещаются в модель UnconfirmedData до тех пор, пока пользователь не внесет свои исправления, после чего они помещаются в модель данных и предпринимается попытка проверки.
  2. Одна модель с пометкой «подтвержденные данные», при которой проверка выполняется вручную, а не проверка Rails.

На практике я склоняюсь к использованию 2 моделей, но я новичок в Rails, поэтому я подумал, что есть более приятный способ сделать это, у Rails есть привычка удивлять меня вот так :)


person Richter    schedule 06.01.2011    source источник


Ответы (2)


Нужно ли сохранять данные между запросами? Если это так, я бы использовал формат двух ваших моделей, но использовал наследование одной таблицы (STI), чтобы все оставалось сухим.

Первая модель, отвечающая за синтаксический анализ и рендеринг, а также за то, что она делает все, что в ее силах, не должна иметь никаких проверок или ограничений на ее сохранение. Однако в миграции должен быть столбец type, чтобы вы могли использовать преимущества наследования. Если вы не понимаете, о чем я говорю, прочтите огромное количество информации о НТИ, хорошей отправной точкой будет полное руководство.

Вторая модель — это та, которую вы будете использовать в остальной части приложения, строгая модель, которая имеет все проверки. Каждый раз, когда пользователь отправлял переработанные и потенциально достоверные данные, ваше приложение пыталось переместить ваш экземпляр открытой модели, созданной из параметров, в экземпляр второй модели и посмотреть, действителен ли он. Если было, сохраните в базу, и атрибут type изменится, и все будет замечательно. Если он недействителен, сохраните первый экземпляр и верните второй экземпляр пользователю, чтобы можно было использовать сообщения об ошибках проверки.

class ArticleData < ActiveRecord::Base
    def parse_from_url(url)
        # parses some stuff from the data source
    end
end

class Article < ArticleData
     validates_presence_of :title, :body
     validates_length_of :title, :greater_than => 20
     # ...
end

Вам понадобится довольно интенсивное действие контроллера, чтобы облегчить описанный выше процесс, но это не должно быть слишком сложно. В остальной части вашего приложения убедитесь, что вы запускаете свои запросы в модели Article, чтобы возвращать только действительные.

Надеюсь это поможет!

person hornairs    schedule 06.01.2011
comment
Большое спасибо за разъяснения, я думаю, что я пойду по этому пути. Данные будут перемещаться между запросами и, возможно, даже сессиями, поэтому будет полезно хранить предварительные данные; это, вероятно, будет более важным в будущем, чем сейчас. Спасибо за ссылку на railsforum, очень полезная. - person Richter; 08.01.2011

Использование одной модели должно быть достаточно простым. Вам понадобится атрибут/метод, чтобы определить, следует ли выполнять проверки. Вы можете передать :if =>, чтобы обойти/включить их:

validates_presence_of :title, :if => :should_validate

should_validate может быть простым логическим атрибутом, возвращающим false, если экземпляр модели является «предварительным», или более сложным методом, если необходимо.

person zetetic    schedule 06.01.2011
comment
Ааа, это та доброта Rails, на которую я надеялся. Однако после реализации как этого, так и метода, описанного выше, я думаю, что пойду по пути двух моделей. Это не так удобно, но позволяет лучше отделить действительные данные от предварительных, что может быть важно в будущем. Большое спасибо за ваш ответ, хотя я не видел :if раньше, без сомнения, он очень скоро пригодится. - person Richter; 08.01.2011