2009-06-10 7 views
4

J'essaie d'utiliser un time_select pour entrer une heure dans un modèle qui effectuera ensuite des calculs. L'assistant time_select prépare les paramètres renvoyés afin qu'ils puissent être utilisés dans une affectation multi-paramètres à un objet Active Record.Rails, en utilisant time_select sur un modèle d'enregistrement non actif

Quelque chose comme le

suivant
Parameters: {"commit"=>"Calculate", "authenticity_token"=>"eQ/wixLHfrboPd/Ol5IkhQ4lENpt9vc4j0PcIw0Iy/M=", "calculator"=>{"time(2i)"=>"6", "time(3i)"=>"10", "time(4i)"=>"17", "time(5i)"=>"15", "time(1i)"=>"2009"}} 

Ma question est, quelle est la meilleure façon d'utiliser ce format dans un modèle d'enregistrement non actif. Aussi sur une note de côté. Quelle est la signification de (5i), (4i) etc.? (Autre que la raison évidente de distinguer les différentes valeurs de temps, essentiellement la raison pour laquelle il a été nommé ainsi)

Merci

Répondre

4

Vous pouvez créer une méthode dans le modèle d'enregistrement non actif comme suit

# This will return a Time object from provided hash 
def parse_calculator_time(hash) 
    Time.parse("#{hash['time1i']}-#{hash['time2i']}-#{hash['time3i']} #{hash['time4i']}:#{hash['time5i']}") 
end 

Vous pouvez ensuite appeler la méthode de l'action du contrôleur comme suit

time_object = YourModel.parse_calculator_time(params[:calculator]) 

Il peut ne pas être la meilleure solution, mais il est simple à utiliser. Cheers :)

+0

Merci beaucoup pour la réponse inestimable. – abhijit

2

La lettre après le numéro représente le type auquel vous souhaitez être jeté. Dans ce cas, integer. Il pourrait également être f pour float ou s pour string. Je viens de le faire moi-même et la façon la plus simple de trouver était de copier/coller le code Rails dans mon module de base (ou objet abstrait).

j'ai copié les fonctions suivantes mot pour mot de ActiveRecord::Base

  • assign_multiparameter_attributes(pairs)
  • extract_callstack_for_multiparameter_attributes(pairs)
  • type_cast_attribute_value(multiparameter_name, value)
  • find_parameter_position(multiparameter_name)

J'ai également les méthodes suivantes qui appellent/les utiliser:

def setup_parameters(params = {}) 
    new_params = {} 
    multi_parameter_attributes = [] 

    params.each do |k,v| 
    if k.to_s.include?("(") 
     multi_parameter_attributes << [ k.to_s, v ] 
    else 
     new_params[k.to_s] = v 
    end 
    end 

    new_params.merge(assign_multiparameter_attributes(multi_parameter_attributes)) 
end 

# Very simplified version of the ActiveRecord::Base method that handles only dates/times 
def execute_callstack_for_multiparameter_attributes(callstack) 
    attributes = {} 

    callstack.each do |name, values| 

    if values.empty? 
     send(name + '=', nil) 
    else 
     value = case values.size 
     when 2 then t = Time.new; Time.local(t.year, t.month, t.day, values[0], values[min], 0, 0) 
     when 5 then t = Time.time_with_datetime_fallback(:local, *values) 
     when 3 then Date.new(*values) 
     else nil 
     end 

     attributes[name.to_s] = value 
    end 

    end 

    attributes 
end 

Si vous trouvez une meilleure solution, s'il vous plaît laissez-moi savoir :-)

+0

Cette solution est-elle pour Rails 3 ou 4? Il ne semble pas fonctionner dans Rails 4 quand je l'essaie. –

+0

@MattHuggins Honnêtement, cela aurait pu être pour Rails 2, donc c'est très ***, ça ne marchera probablement pas dans Rails 4. –

+0

On dirait que c'est toujours un problème avec Rails 4.0.1. Il y a un problème ouvert pour cela: https://github.com/rails/rails/pull/8189 –

Questions connexes