2010-03-29 5 views
0

J'ai un problème que je ne sais pas comment réparer. Cela a à voir avec le hash params non trié.Params commande dans Foo.new (params [: foo]), besoin d'un avant l'autre (Rails)

J'ai un objet Réservation qui a un attribut time = virtuel et un attribut eating_session = virtuel quand je règle le temps = je veux aussi le valider via une requête de serveur externe. Je le fais avec l'aide de la méthode times() qui effectue une recherche sur un autre serveur et enregistre tous les temps possibles dans la variable @times. Le problème est maintenant que la méthode times() a besoin de l'attribut eating_session pour savoir quels sont les temps valides, mais les rails appellent parfois la méthode times =, avant qu'il y ait un eat_session dans l'objet Reservation quand je fais juste @ réservation = Reservation.new (params [: réservation])

class ReservationsController < ApplicationController 
    def new 
     @reservation = Reservation.new(params[:reservation]) 
     # ... 
    end 
end 

class Reservation < ActiveRecord::Base 
    include SoapClient 
    attr_accessor :date, :time 
    belongs_to :eating_session 

    def time=(time) 
     @time = times.find { |t| t[:time] == time } 
    end 

    def times 
     return @times if defined? @times 
     @times = [] 
     response = call_soap :search_availability { 
      # eating_session is sometimes nil 
      :session_id => eating_session.code, # <- HERE IS THE PROBLEM 
      :dining_date => date 
     } 
     response[:result].each do |result| 
      @times << { 
       :time => "#{DateTime.parse(result[:time]).strftime("%H:%M")}", 
       :correlation_data => result[:correlation_data] 
      } 
     end 
     @times 
    end 
end 

Je ne sais pas comment résoudre ce problème, toute aide est apriciated.

Répondre

0

Ce que je fais souvent dans ce cas est de pousser le code dépendant dans une validation:

class ReservationsController < ApplicationController 
    def new 
     @reservation = Reservation.new(params[:reservation]) 
     # ... 
    end 
end 

class Reservation < ActiveRecord::Base 
    include SoapClient 
    attr_accessor :date, :time 
    belongs_to :eating_session 
    validate :validate_time 

    def validate_time 
     errors.add_to_base "Time is invalid" unless @time = times.find { |t| t[:time] == time } 
    end 

    def times 
     return @times if defined? @times 
     @times = [] 
     response = call_soap :search_availability { 
      # eating_session is sometimes nil 
      :session_id => eating_session.code, # <- HERE IS THE PROBLEM 
      :dining_date => date 
     } 
     response[:result].each do |result| 
      @times << { 
       :time => "#{DateTime.parse(result[:time]).strftime("%H:%M")}", 
       :correlation_data => result[:correlation_data] 
      } 
     end 
     @times 
    end 
end 
+0

Comment cela aide? Je ne comprends pas. La méthode time = sera appelée avant le paramètre seating_session = que j'aie ou non validé: validate_time dans mon code, ou est-ce que je comprends quelque chose de mal? – Jeena

+0

J'ai supprimé votre méthode time =. Le fait est que les paramètres de commande traités ne sont pas définis, mais vous pouvez garantir que les validations seront exécutées * après que * tous les paramètres aient été définis. J'ai donc déplacé votre fonctionnalité hors de l'accesseur et dans une validation. Cela a-t-il du sens? – Gareth

+0

Mais alors je devrais supprimer: time de attr_accessor: date,: time aussi? – Jeena