rails que ejemplos descargar curso ruby-on-rails ruby time duration

ruby on rails - que - Usar un campo de duración en un modelo de Rails



ruby time difference (4)

Estoy buscando la mejor manera de usar un campo de duración en un modelo de Rails. Me gustaría que el formato sea HH: MM: SS (ej .: 01:30:23). La base de datos en uso es sqlite localmente y Postgres en producción.

También me gustaría trabajar con este campo para poder ver todos los objetos en el campo y obtener el tiempo total de todos los objetos en ese modelo y terminar con algo como:

30 registros que suman 45 horas, 25 minutos y 34 segundos.

Entonces, ¿qué funcionaría mejor?

  • Tipo de campo para la migración
  • ¿Campo de formulario para los formularios CRUD (hora, minuto, segundo desplegable?)
  • Método menos costoso para generar la duración total de todos los registros en el modelo

En Rails 5, puede usar ActiveRecord :: Attributes para almacenar ActiveSupport :: Durations como cadenas ISO8601. La ventaja de utilizar ActiveSupport :: Duration en enteros es que puede usarlos para cálculos de fecha / hora al instante. Puedes hacer cosas como Time.now + 1.month y siempre es correcto.

Así es cómo:

Agregar config/initializers/duration_type.rb

class DurationType < ActiveRecord::Type::String def cast(value) return value if value.blank? || value.is_a?(ActiveSupport::Duration) ActiveSupport::Duration.parse(value) end def serialize(duration) duration ? duration.iso8601 : nil end end ActiveRecord::Type.register(:duration, DurationType)

Migración

create_table :somethings do |t| t.string :duration end

Modelo

class Something < ApplicationRecord attribute :duration, :duration end

Uso

something = Something.new something.duration = 1.year # 1 year something.duration = nil something.duration = "P2M3D" # 2 months, 3 days (ISO8601 string) Time.now + something.duration # calculation is always correct



Intenté usar ActiveSupport :: Duration, pero tuve problemas para obtener la salida clara.

Puede que le guste ruby-duration , un tipo inmutable que representa cierta cantidad de tiempo con precisión en segundos. Tiene muchas pruebas y un tipo de campo modelo Mongoid.

También quería analizar fácilmente las secuencias de duración humana, así que fui con Duración crónica . Aquí hay un ejemplo de agregarlo a un modelo que tiene un campo time_spent in seconds.

class Completion < ActiveRecord::Base belongs_to :task belongs_to :user def time_spent_text ChronicDuration.output time_spent end def time_spent_text= text self.time_spent = ChronicDuration.parse text logger.debug "time_spent: ''#{self.time_spent_text}'' for text ''#{text}''" end end


  • Almacene como enteros en su base de datos (probablemente sea el número de segundos).
  • Su formulario de inscripción dependerá del caso de uso exacto. Los desplegables son dolorosos; es mejor usar campos de texto pequeños para la duración en horas + minutos + segundos.
  • Simplemente ejecute una consulta SUM en la columna de duración para generar un total general. Si usas números enteros, esto es fácil y rápido.

Adicionalmente:

  • Use un ayudante para mostrar la duración en sus vistas. Puede convertir fácilmente una duración como un número entero de segundos en ActiveSupport::Duration utilizando 123.seconds (reemplace 123 con el número entero de la base de datos). Utilice inspect la Duration resultante para un buen formato. (No es perfecto. Puede escribir algo usted mismo).
  • En su modelo, probablemente querrá lectores de atributos y escritores que devuelvan / tomen ActiveSupport::Duration objects, en lugar de enteros. Simplemente defina duration=(new_duration) y duration , que internamente read_attribute / write_attribute con argumentos enteros.