2010-12-14 36 views
1

Je souhaite mettre en forme les données entrées dans une colonne de chaîne (portant le nom time) de ma base de données d'une certaine manière. En raison des problèmes de données hérités sur ce projet, je ne peux pas simplement changer le type de colonne de la chaîne à l'heure parce que je perdrais les vieilles entrées.Formater la façon dont une chaîne est entrée dans ma base de données

Je veux simplement exiger que le format des informations saisies dans le formulaire, puis soumis à la base de données est la suivante:

00:00 where a 0 can by any integer 0-9.

Comment pourrais-je faire cela dans un form_for. Je utilise Rails 2.3.8.

+0

Vous pouvez modifier le type de champ, mais il faut plusieurs étapes. Que ça vaut la peine est la prochaine question. –

+0

Oui ... Je ne veux pas vraiment changer le type de champ. Je cherche simplement un moyen de formater les données. – bgadoci

+0

Si je devais changer le type de champ ... les données existantes pourraient-elles être mappées? – bgadoci

Répondre

0

Votre regex serait /\d\d:\d\d/, mais je ne suis pas sûr de savoir comment utiliser les expressions régulières dans Ruby.

+0

En fait, ce n'est pas une regex. Peut-être que vous vouliez dire «\ d»? –

+0

Eek! Oui, c'est ce que je voulais dire. –

0

Votre regex serait:

/[0-9]{2}:[0-9]{2}/ 

ou

/\d\d:\d\d/ 

Voici quelques tests:

'00:00'[/[0-9]{2}:[0-9]{2}/] # => "00:00" 
'12:00'[/\d\d:\d\d/]   # => "12:00" 
'11:59'[/[0-9]{2}:[0-9]{2}/] # => "11:59" 
'23:59'[/\d\d:\d\d/]   # => "23:59" 

':'[/[0-9]{2}:[0-9]{2}/] # => nil 
':0'[/[0-9]{2}:[0-9]{2}/] # => nil 
'0:0'[/[0-9]{2}:[0-9]{2}/] # => nil 
'000:0'[/[0-9]{2}:[0-9]{2}/] # => nil 
'0:000'[/[0-9]{2}:[0-9]{2}/] # => nil 

Jusqu'à ce point, je travaillais avec votre solution spécifiée, mais voici où il se décompose:

# BUG? 
'1:00'[/[0-9]{2}:[0-9]{2}/] # => nil 

# Fix? 
'1:00'[/[0-9]{1,2}:[0-9]{2}/] # => "1:00" 

# *** BUG *** 
'99:99'[/[0-9]{2}:[0-9]{2}/] # => "99:99" 

Notez que '99: 99' est accepté.

Essayer d'utiliser une regex pour vérifier la plage n'est pas très pratique lorsque l'on traite quelque chose comme une valeur de temps. Cela peut être fait, mais la regex devient moche.

Voici le début d'une solution. Finition des essais pour la gamme appropriée est laissée en exercice pour le lecteur:

timeval = '00:00'[/[0-9]{2}:[0-9]{2}/] 
(timeval.split(':').map(&:to_i) <=> [11,59]) <= 0 # => true 

timeval = '1:00'[/[0-9]{1,2}:[0-9]{2}/] 
(timeval.split(':').map(&:to_i) <=> [11,59]) <= 0 # => true 

timeval = '1:00'[/[0-9]{1,2}:[0-9]{2}/] 
(timeval.split(':').map(&:to_i) <=> [11,59]) <= 0 # => true 

timeval = '0:99'[/[0-9]{1,2}:[0-9]{2}/] 
(timeval.split(':').map(&:to_i) <=> [11,59]) <= 0 # => true 

timeval = '99:99'[/[0-9]{1,2}:[0-9]{2}/] 
(timeval.split(':').map(&:to_i) <=> [11,59]) <= 0 # => false 

Alternativement, vous pouvez regarder dans une <select> popups for the values, ou un plugin jQuery qui est conçu pour l'entrée de temps, ou quelque chose comme validates_timeliness ou validates_date_time. J'ai également trouvé time_select with 12 hour time and Time Zone in Ruby on Rails. Vous pouvez aussi search Stack Overflow.

+0

Ok, alors comment cela pourrait-il être implémenté? Y aurait-il un ajout au modèle Run? Pourriez-vous me donner quelques détails sur ce qui irait où (modèle, vue). J'ai environ 1,5 ans dans les rails et donc les deux expressions reg et test ne sont pas des choses que j'ai encore maîtrisées. – bgadoci

1

Un travail autour qui pourrait aider:

d'abord créer une migration faisant:

rename_column :the_models, :time, :old_time 
add_column :the_models, :time, :time 

Alors maintenant, le modèle aura un champ appelé old_time contenant les données de temps d'origine, et un nouveau champ time avoir le bon type de champ. Par conséquent, les formulaires existants sembleraient comme perdu toutes les données de temps, mais au moins ils appellent the_model.time pour obtenir le résultat.

Le vrai travail autour d'une partie:

class TheModel < ActiveRecord::Base 
    def time 
    read_attribute(:time) || Time.parse(read_attribute(:old_time)) 
    end 
end 

Alors maintenant, la valeur temporelle sera enregistrée dans le time déposé.

Lorsque time est nul, il essaie d'obtenir la valeur de temps du old_time et de le convertir en objet temporel.

Il y a deux inconvénients:

  1. Time.parse (« 12:34 ») vous donnerait quelque chose comme: 2010-12-14 12:34:00 +0800 Parce que vous avez donné que l'heure et minutes, d'autres champs ne sont pas fiables.
  2. Vous avez un champ presque obsolète appelé old_time dans la base de données. Donc, dans le futur, vous voudrez peut-être supprimer complètement ce champ, après avoir été sûr que toutes les valeurs old_time ont été converties dans le champ time.

Une note plus:

Vous devez convertir les formulaires existants, pour le champ :time qui probablement en utilisant text_field. Le champ text_field peut devenir quelque chose comme 2010-12-14 12:34:00 +0800.

Si vous voulez vraiment continuer à utiliser text_field, vous pouvez:

def time 
    t = read_attribute(:time) 
    t.nil? ? read_attribute(:old_time) : t.strftime("%H:%M") 
end 

def time=(val) 
    write_attribute(:time, Time.parse(val)) 
end