Как проверить ввод по записям базы данных, чтобы избежать наложения? - PullRequest
0 голосов
/ 25 апреля 2019

Работа над приложением для управления встречами с Ruby on Rails и попытка реализовать проверку с перекрытием.Встречи имеют время начала и окончания (не в формате DateTime, просто целые числа)

Пытался использовать диапазоны, но это не сработало

Ожидается достижение следующего:

База данных существующих записей:

[{id:1, start_time:0; end_time:10}, {id:2, start_time:20, end_time:40}]

Следует проверить новый объект встречи, чтобы убедиться, что он не перекрывается с другими встречами, т.е.

{id:15, start_time:11, end_time:19} должен быть успешно сохранен

{id:16, start_time:1, end_time:9} не должен быть сохранен (перекрывается с другой встречей (id 1))

Ответы [ 2 ]

0 голосов
/ 26 апреля 2019

Прежде всего измените эти столбцы на типы даты и времени, чтобы вы могли использовать функции даты в базах данных.Зачем использовать целые числа, если ваша база данных действительно может правильно представлять время / дату?

В SQL есть ключевое слово OVERLAPS, которое можно использовать для проверки перекрытий между двумя временными метками:

SELECT  "appointments".* FROM "appointments" 
WHERE ((start_time, end_time) OVERLAPS (a, b)) 

Postgres поддерживаетЭто.MySQL, являющийся крестьянской базой данных, требует хакерского обходного пути .

. Вы можете создать "область видимости" из этого следующим образом:

class Appointment < ApplicationRecord
  def self.overlapping(range)
    self.where('(?,?) OVERLAPS (starts_at, ends_at)', range.begin, range.end)
  end
end

Затем можно использовать область в Пользовательская проверка :

class Appointment < ApplicationRecord
  validates :time_available
  def self.overlapping(range)
    self.where('(?,?) OVERLAPS (starts_at, ends_at)', range.begin, range.end)
  end

  def time_available
    if self.class.overlapping(start_time..end_time).exists?
      errors.add(:base, "time is not available") 
    end
  end
end
0 голосов
/ 25 апреля 2019

Вы можете написать пользовательскую проверку. Вместо validates вы бы использовали validate. Вы будете хотеть использовать даты, все же. С чистыми целыми числами вы сможете обрабатывать только один день, если только вы не удаляете все записи каждый день (что делать не нужно). Псевдокод внутри определения.

validate :no_overlap, on: :save

def no_overlap
  # iterate through appointments on that date
  # check for the overlap
  # if overlap exists
  # self.errors.add("Overlaps with existing appointment!")
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...