ruby-on-rails - validates - validate form rails
¿Cómo valido una fecha en los rieles? (9)
Quiero validar una fecha en mi modelo en Ruby on Rails; sin embargo, los valores de día, mes y año ya se han convertido en una fecha incorrecta para cuando llegan a mi modelo.
Por ejemplo, si ingreso el 31 de febrero de 2009 en mi opinión, cuando uso Model.new(params[:model])
en mi controlador, lo convierte en "3 de marzo de 2009", que luego mi modelo ve como una fecha válida. cuál es, pero es incorrecto
Me gustaría poder hacer esta validación en mi modelo. ¿Hay alguna manera que yo pueda, o estoy yendo sobre esto completamente equivocado?
Encontré esta " Validación de fecha " que discute el problema pero nunca se resolvió.
¿Has probado el complemento validates_date_time
?
Active Record le _before_type_cast
atributos _before_type_cast
que contienen los datos de atributo sin procesar antes del encasillado. Esto puede ser útil para devolver mensajes de error con valores previos a la transmisión o simplemente hacer validaciones que no son posibles después de la conversión.
Me abstendría de la sugerencia de Daniel Von Fange de anular el acceso, ya que al hacer la validación en un acceso, el contrato de acceso cambia ligeramente. Active Record tiene una función explícitamente para esta situación. Úselo.
Aquí hay una respuesta no crónica ...
class Pimping < ActiveRecord::Base
validate :valid_date?
def valid_date?
if scheduled_on.present?
unless scheduled_on.is_a?(Time)
errors.add(:scheduled_on, "Is an invalid date.")
end
end
end
Como necesita manejar la cadena de fecha antes de que se convierta a una fecha en su modelo, anularía el acceso para ese campo
Digamos que su campo de fecha es published_date
. Agregue esto a su objeto modelo:
def published_date=(value)
# do sanity checking here
# then hand it back to rails to convert and store
self.write_attribute(:published_date, value)
end
Puede validar la fecha y la hora de esa manera (en un método en algún lugar de su controlador con acceso a sus parámetros si está utilizando selecciones personalizadas) ...
# Set parameters
year = params[:date][:year].to_i
month = params[:date][:month].to_i
mday = params[:date][:mday].to_i
hour = params[:date][:hour].to_i
minute = params[:date][:minute].to_i
# Validate date, time and hour
valid_date = Date.valid_date? year, month, mday
valid_hour = (0..23).to_a.include? hour
valid_minute = (0..59).to_a.include? minute
valid_time = valid_hour && valid_minute
# Check if parameters are valid and generate appropriate date
if valid_date && valid_time
second = 0
offset = ''0''
DateTime.civil(year, month, mday, hour, minute, second, offset)
else
# Some fallback if you want like ...
DateTime.current.utc
end
Si quieres compatibilidad con Rails 3 o Ruby 1.9, prueba con la gema date_validator .
Supongo que estás usando el helper date_select
para generar las etiquetas para la fecha. Otra forma de hacerlo es utilizar select form helper para los campos de día, mes y año. Me gusta esto (el ejemplo que utilicé es el campo de fecha created_at):
<%= f.select :month, (1..12).to_a, selected: @user.created_at.month %>
<%= f.select :day, (1..31).to_a, selected: @user.created_at.day %>
<%= f.select :year, ((Time.now.year - 20)..Time.now.year).to_a, selected: @user.created_at.year %>
Y en el modelo, valida la fecha:
attr_accessor :month, :day, :year
validate :validate_created_at
private
def convert_created_at
begin
self.created_at = Date.civil(self.year.to_i, self.month.to_i, self.day.to_i)
rescue ArgumentError
false
end
end
def validate_created_at
errors.add("Created at date", "is invalid.") unless convert_created_at
end
Si está buscando una solución de complemento, debería consultar el complemento validates_timeliness . Funciona así (desde la página de github):
class Person < ActiveRecord::Base
validates_date :date_of_birth, on_or_before: lambda { Date.current }
# or
validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date }
end
La lista de métodos de validación disponibles es la siguiente:
validates_date - validate value as date
validates_time - validate value as time only i.e. ''12:20pm''
validates_datetime - validate value as a full date and time
validates - use the :timeliness key and set the type in the hash.
Un poco tarde aquí, pero gracias a " ¿Cómo valido una fecha en los rieles? " Logré escribir este validador, la esperanza es útil para alguien:
Dentro de tu model.rb
validate :date_field_must_be_a_date_or_blank
# If your field is called :date_field, use :date_field_before_type_cast
def date_field_must_be_a_date_or_blank
date_field_before_type_cast.to_date
rescue ArgumentError
errors.add(:birthday, :invalid)
end
Usando la gema crónica:
class MyModel < ActiveRecord::Base
validate :valid_date?
def valid_date?
unless Chronic.parse(from_date)
errors.add(:from_date, "is missing or invalid")
end
end
end