Я работаю над изучением RoR. У меня есть одно требование к вводу дат от пользователя, но это всегда должна быть текущая дата или будущее. Во входных данных пользователь вводит дату начала и дату окончания. В настоящее время я использую приведенный ниже синтаксис и вспомогательный класс для выбора даты и времени.
<div class = "field">
<%= form.label :start_time %>
<%= form.datetime_select :start_time %>
</div>
Согласно текущей форме, это то, что пользователь может выбрать из формы:
Здесь я хотел выбрать диапазон даты и времени таким образом, чтобы он всегда был от текущей даты, а не от старой даты.
Здесь я хочу получить информацию о будущих событиях от пользователя и сохранить в базе данных.
Ниже представлена модель событий:
class Event < ApplicationRecord
validates :start_time, presence: true
validates :end_time, presence: true
validate :valid_start_and_end_time
def start_time
super || end_time
end
private
def valid_start_and_end_time
start_time <= end_time
end
end
и EventController:
class EventsController < ApplicationController
before_action :set_event only: [:show, :edit, :update, :destroy]
def index
@event = Event.all.where('start_time > ?', Time.now).sort_by(&:start_time).sort_by(&:title)
end
def create
@event = Event.new(event_params)
@event.save
end
private
def event_params
params.require(:event).permit(:title, :start_time, :end_time)
end
end
По сути, что я хочу здесь сделать:
1. Мы хотим, чтобы пользователь ввел дату начала и время окончания, все это должно быть будущими событиями или, по крайней мере, добавить проверку.
2. В модели мы хотим отсортировать индекс событий по времени начала, а затем по заголовку.
Может кто-нибудь, пожалуйста, помогите мне понять, как это можно сделать наилучшим образом, чтобы я мог улучшить свое обучение в RoR.
Любая помощь здесь будет очень признательна.
🤔 А знаете ли вы, что...
Ruby on Rails позволяет использовать компоненты фронтенда, такие как AngularJS или React, с помощью API-режима.
Вы можете проверить, что start_time
не может находиться в прошлом, с помощью валидатора сравнения (добавленного в Rails 7):
validates :start_time, comparison: { greater_than_or_equal_to: Time.current }
Вы также можете проверить, что end_time
должен быть после start_time
или равен ему, с помощью валидатора сравнения:
validates :end_time, comparison: { greater_than_or_equal_to: :start_time }
Эти две проверки также проверяют наличие атрибута по умолчанию, поэтому с их помощью вы гарантируете, что start_time
и end_time
оба присутствуют, а не в прошлом, и что end_time
находится после start_time
или равен ему.
Это означает, что вы можете удалить validates :start_time, presence: true
, validates :end_time, presence: true
и свой собственный validate :valid_start_and_end_time
.
Вы можете отсортировать события по start_time, а затем по названию, например:
Event.order(start_time: :asc, title: :asc)
что преобразуется в этот SQL-запрос:
SELECT
events.*
FROM
events
ORDER BY
events.start_time ASC,
events.title ASC
и дает вам события, упорядоченные по start_date
(от самых старых до самых новых), а затем по title
(в алфавитном порядке).
В Rails эти часто используемые запросы очень часто встречаются в областях . Вы бы написали это так:
scope :sorted, -> { order(start_time: :asc, title: :asc) }
После определения этой области вместо Event.order(start_time: :asc, title: :asc)
вы можете использовать Event.sorted
.
Поскольку вы используете where('start_time > ?', Time.now)
в контроллере событий, я предполагаю, что вам также нужна область для этого, которую вы можете определить следующим образом:
scope :upcoming, -> { where('start_time > ?', Time.current) }
Ваше индексное действие теперь можно переписать так:
def index
@events = Event.upcoming.sorted
end
который выполняет этот SQL-запрос:
SELECT
events.*
FROM
events
WHERE
(start_time > '2024-05-10 21:03:50.413480') -- the current time
ORDER BY
events.start_time ASC,
events.title ASC