ruby-on-rails - qué - seguridad en ruby on rails
Cómo funcionan los atributos de múltiples parámetros de Ruby on Rails*realmente*(datetime_select) (2)
Creo que datetime_select
es magia negra. Lo que realmente estoy tratando de averiguar es todo lo relacionado con 1i
, 2i
, 3i
, 4i
... múltiples parámetros. Específicamente, ¿cómo se maneja en el back-end (activerecord, algo más?). ¿Qué pasa con la ''i'' después del número de pedido? ¿Es un especificador de tipo? Si es así, ¿qué otros tipos están disponibles? He leído la fuente de date_helper.rb y es bastante opaca.
Aquí está mi motivación:
Tengo una columna :datetime
en mi modelo y quiero ingresar en la vista a través de dos text_field
s: uno para la fecha y otro para la hora. Deben validarse, fusionarse y luego almacenarse en la columna de fecha y hora. En última instancia, usaré un calendario de javascript para ingresar fechas en el campo de fecha.
¿Alguien ha hecho esto? Intenté usar atributos virtuales (increíblemente indocumentados además del rudimentario railscast) y el problema fue que cuando se crea un nuevo objeto activerecord y tiene atributos nil, el atributo virtual falla (método indefinido strftime
para nil class, lo que tiene sentido).
¿Alguien tiene alguna sugerencia o buenas prácticas? ¡Gracias!
Esto es lo que acabé de encontrar. Si alguien tiene algún comentario, hágamelo saber. Me encantaría recibir comentarios.
validate :datetime_format_and_existence_is_valid
before_save :merge_and_set_datetime
# virtual attributes for date and time allow strings
# representing date and time respectively to be sent
# back to the model where they are merged and parsed
# into a datetime object in activerecord
def date
if (self.datetime) then self.datetime.strftime "%Y-%m-%d"
else @date ||= (Time.now + 2.days).strftime "%Y-%m-%d" #default
end
end
def date=(date_string)
@date = date_string.strip
end
def time
if(self.datetime) then self.datetime.strftime "%l:%M %p"
else @time ||= "7:00 PM" #default
end
end
def time=(time_string)
@time = time_string.strip
end
# if parsing of the merged date and time strings is
# unsuccessful, add an error to the queue and fail
# validation with a message
def datetime_format_and_existence_is_valid
errors.add(:date, ''must be in YYYY-MM-DD format'') unless
(@date =~ //d{4}-/d/d-/d/d/) # check the date''s format
errors.add(:time, ''must be in HH:MM format'') unless # check the time''s format
(@time =~ /^((0?[1-9]|1[012])(:[0-5]/d){0,2}(/ [AaPp][Mm]))$|^(([01]/d|2[0-3])(:[0-5]/d){0,2})$/)
# build the complete date + time string and parse
@datetime_str = @date + " " + @time
errors.add(:datetime, "doesn''t exist") if
((DateTime.parse(@datetime_str) rescue ArgumentError) == ArgumentError)
end
# callback method takes constituent strings for date and
# time, joins them and parses them into a datetime, then
# writes this datetime to the object
private
def merge_and_set_datetime
self.datetime = DateTime.parse(@datetime_str) if errors.empty?
end
Tenía la misma pregunta. Esto es lo que encontré ...
http://apidock.com/rails/ActiveRecord/Base/assign_multiparameter_attributes
assign_multiparameter_attributes (pares) privado
Crea una instancia de los objetos para todas las clases de atributos que necesitan más de un parámetro de constructor. Esto se hace llamando al nuevo objeto de tipo de columna o tipo de agregación (a través de compos_of) con estos parámetros. Entonces, al tener los pares written_on (1) = "2004", written_on (2) = "6", written_on (3) = "24", se creará una instancia de writing_on (un tipo de fecha) con Date.new ("2004", "6 "," 24 "). También puede especificar un carácter de cadena de caracteres entre paréntesis para que los parámetros sean tipificados antes de que se utilicen en el constructor. Use i para Fixnum, f para Float, s para String y a para Array. Si todos los valores de un atributo dado están vacíos, el atributo se establecerá en nulo.
Así que los números son para los parámetros del tipo de datos que es la columna. La "i" es convertirlo en un entero. Se admiten otros tipos como "f" para flotar, etc.
Puede ver aquí en execute_callstack_for_multiparameter_attributes que detecta el tipo de destino y lo instancia pasando los valores.
Por lo tanto, para intentar responder directamente a la pregunta planteada, no creo que pueda usarla para anular la forma en que se crea un DateTime porque utiliza el constructor que no admite el formato que desea transmitir. divida la columna DateTime en una columna Date y Time. Entonces la interfaz de usuario podría funcionar como yo quería.
Me pregunto si podría ser posible crear accesores de atributos en la clase que representen la fecha y la hora por separado, pero mantener una sola columna DateTime. Entonces la forma podría hacer referencia a esos accesores separados. Eso podría ser viable. Otra opción podría ser utilizar composed_of para personalizar aún más el tipo.
Espero que ayude a alguien más. :)