PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Problèmes avec une plage de temps infinie dans Rails

Vous ne pouvez pas stocker Infinity dans le cadre d'une plage horaire dans Rails. Je pense que c'est parce qu'Infinity va être inséré en tant que valeur de chaîne et interprété comme un flotteur lorsqu'il est extrait de l'oid PSQL natif. Ainsi, toute plage de dates de Date -> Float ne sera pas viable. Mais vous pouvez réussir à créer votre propre plage avec des dates pseudo (1 million d'années à partir de maintenant) ou vous pouvez simplement utiliser deux champs de date distincts et les interpréter de manière appropriée dans le modèle. Date de début, date de fin.

Dans Rails 4.2+, vous pouvez stocker une valeur Float ::INFINITY dans votre type datetime. Exemple.

User.first.update(begin_date: DateTime.now, end_date: 'infinity')
User.first.end_date # => Infinity

Cependant, end_date ne sera pas une date valide. Vous stockez simplement la chaîne dans la base de données et vous sortez un flottant quand vous l'appelez.

Voici le code réel (Rails 4.2) qui gère cela :

module ActiveRecord
  module ConnectionAdapters
    module PostgreSQL
      module OID # :nodoc:
        class DateTime < Type::DateTime # :nodoc:
          include Infinity

          def type_cast_for_database(value)
            if has_precision? && value.acts_like?(:time) && value.year <= 0
              bce_year = format("%04d", -value.year + 1)
              super.sub(/^-?\d+/, bce_year) + " BC"
            else
              super
            end
          end

          def cast_value(value)
            if value.is_a?(::String)
              case value
              when 'infinity' then ::Float::INFINITY
              when '-infinity' then -::Float::INFINITY
              when / BC$/
                astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
                super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
              else
                super
              end
            else
              value
            end
          end
        end
      end
    end
  end
end

Encore une fois, vous ne serez pas être capable de faire des comparaisons de date et d'heure avec un flottant. Mais, il est probablement assez simple d'avoir un cas particulier pour ces deux valeurs -::Float::INFINITY et ::Float::INFINITY