2010-03-11 7 views
0

J'ai une table de périodes qui a start_at: datetime end_at: datetime. Étant donné que chaque période commence et se termine à la même date, je souhaite séparer les trois champs au lieu de deux.Menus multi-sélection et attributs virtuels

champ 1: la date champ 2: l'heure "00:00" de départ champ 3: le temps "00:00" de fin

j'ai commencé et fait cela. Mais malheureusement, j'ai fait face à un problème.

Alors s'il vous plaît jeter un oeil au modèle de période, la forme et l'erreur, et corrigez-moi, corrigez le code.

Merci d'avance!

modèle de période

class Period < ActiveRecord::Base 
    belongs_to :show 

    def show_date; start_at.nil? ? Time.now.to_date : start_at.to_date; end 
    def start_at_time; start_at.nil? ? Time.now.to_time : start_at.to_time; end 
    def end_at_time; end_at.nil? ? Time.now.to_time : end_at.to_time; end 

    def start_at_time=(start_str) 
    self.start_at = DateTime.parse("#{show_date.strftime("%Y-%m-%d")}T#{start_str.strftime("%H:%M:%S")}") 
    end 

    def end_at_time=(end_str) 
    self.end_at = DateTime.parse("#{show_date.strftime("%Y-%m-%d")}T#{end_str.strftime("%H:%M:%S")}") 
    end 
end 

Périodes schéma

#just the schema for periods table 
    create_table "periods", :force => true do |t| 
    t.integer "show_id" 
    t.datetime "start_at" 
    t.datetime "end_at" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

_form.html.erb

<div class="group"> 
    <%= f.label :show_id, "Show", :class => :label %> 
    <%= f.collection_select :show_id, @shows.collect, :id, :name %> 
    <span class="description">Select the show</span> 
    </div> 

    <div class="group"> 
    <%= f.label :show_date, "Date at", :class => :label %> 
    <%= f.date_select :show_date, :class => 'datetime_select' %> 
    <span class="description">Date of the show</span> 
    </div> 

    <div class="group"> 
    <%= f.label :start_at_time, "Start at", :class => :label %> 
    <%= f.time_select :start_at_time, {:minute_step => 15, :ignore_date => true}, :class => 'datetime_select' %> 
    <span class="description">Time :: When does it start?</span> 
    </div> 

    <div class="group"> 
    <%= f.label :end_at_time, "End at", :class => :label %> 
    <%= f.time_select :end_at_time, {:minute_step => 15, :ignore_date => true}, :class => 'datetime_select' %> 
    <span class="description">Time :: When does it end?</span> 
    </div> 

    <div> 
    <button class="button" type="submit"><%= image_tag("tick.png", :alt => "Save") %> Save</button> 
    </div> 

L'erreur

==Framework Trace 

3 error(s) on assignment of multiparameter attributes 



==Framework Trace 

/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:3073:in `execute_callstack_for_multiparameter_attributes' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:3028:in `assign_multiparameter_attributes' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2750:in `attributes=' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2628:in `update_attributes' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:1331:in `send' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:1331:in `perform_action_without_filters' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/filters.rb:617:in `call_filters' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 
/home/amrnt/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/benchmark.rb:17:in `ms' 
/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime' 
/home/amrnt/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/benchmark.rb:17:in `ms' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/rescue.rb:160:in `perform_action_without_flash' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/flash.rb:146:in `perform_action' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:532:in `send' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:532:in `process_without_filters' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/filters.rb:606:in `sass_old_process' 
/usr/lib/ruby/gems/1.8/gems/haml-2.3.0/lib/sass/plugin/rails.rb:19:in `process_without_compass' 
/home/amrnt/cc/vendor/gems/compass-0.8.17/lib/compass/app_integration/rails/action_controller.rb:7:in `process' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:391:in `process' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:386:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/routing/route_set.rb:437:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:87:in `dispatch' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:121:in `_call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:130:in `build_middleware_stack' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/query_cache.rb:29:in `call' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/query_cache.rb:29:in `call' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/query_cache.rb:9:in `cache' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/query_cache.rb:28:in `call' 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/string_coercion.rb:25:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/head.rb:9:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/methodoverride.rb:24:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:15:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/session/cookie_store.rb:93:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/failsafe.rb:26:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:114:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/reloader.rb:34:in `run' 
/home/amrnt/.gem/ruby/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:108:in `call' 
/usr/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/static.rb:31:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call' 
/usr/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/log_tailer.rb:17:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:13:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/chunked.rb:15:in `call' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:64:in `process' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new' 
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run' 
/home/amrnt/.gem/ruby/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:34:in `run' 
/usr/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/commands/server.rb:111 
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 
script/server:3 



==Request Parameters: 

{"period"=>{"start_at_time(4i)"=>"20", 
"start_at_time(5i)"=>"00", 
"end_at_time(4i)"=>"23", 
"end_at_time(5i)"=>"30", 
"show_date(1i)"=>"2010", 
"show_date(2i)"=>"3", 
"show_date(3i)"=>"31", 
"show_id"=>"1"}, 
"_method"=>"put", 
"authenticity_token"=>"pm/cXQQnOCsidcAj/OEJuMtHgfppZvoqq09epdETAxo=", 
"id"=>"46"} 

Répondre

3

Les date and time form helpers inclus dans ActionView génèrent des éléments de formulaire spéciaux qui utilisent quelque chose appelé "affectation multiparamètre". Cela signifie que lorsque vous soumettez les champs de formulaire date_select, datetime_select ou time_select, ils génèrent plusieurs paramètres séparés qui sont compilés par ActiveRecord en un objet date, date ou heure. Dans votre cas, ces paramètres ressemblent:

"start_at_time(4i)"=>"20", 
"start_at_time(5i)"=>"00" 

"end_at_time(4i)"=>"23", 
"end_at_time(5i)"=>"30" 

"show_date(1i)"=>"2010", 
"show_date(2i)"=>"3", 
"show_date(3i)"=>"31" 

Je note que ceux-ci sont très différents des chaînes que vous attendez dans votre méthodes de modèle de période start_at_time= et end_at_time= et que votre modèle ne dispose pas d'une méthode show_date= du tout.

Ce format de paramètre, avec des parenthèses, est ce que Rails utilise pour l'affectation multiparamètre. Cependant, ActiveRecord s'appuie sur une colonne de base de données correspondante pour savoir si les multiples paramètres soumis représentent un objet date, heure ou date/heure. Cela signifie que les helpers ne travailleront pas sur les attributs virtuels, au moins prêts à l'emploi. Il n'y a aucun moyen de dire quel genre d'objet ils attendent.

Il y a au moins un billet actif à ce sujet:

https://rails.lighthouseapp.com/projects/8994/tickets/2675-support-for-multiparameter-attribute-assignment-on-virtual-attribute-writers

Et vous pouvez trouver un aperçu de l'affectation multiparamétrique et l'utilisation des aides de formulaire de date avec Rails à ce lien:

http://www.alexrothenberg.com/2009/05/how-to-use-dates-in-rails-when-your.html

Concernant l'amélioration générale de ce design: si chaque période commence et se termine à la même date, pourquoi ne pas utiliser un attribut date pour stocker la période d mangé et deux time attributs pour stocker les heures de début et de fin. Vous pouvez facilement créer des méthodes qui renvoient des objets datetime start_at et end_at qui sont compilés à partir de ces attributs.

Vous pouvez configurer votre formulaire en utilisant les aides de formulaire plus ou moins comme vous l'avez déjà fait. Vous pouvez également facilement mettre en place une validation sur l'attribut end_time, en veillant à ce qu'il soit toujours plus tard dans la journée que le start_time.

+0

La meilleure solution est que vous avez mentionné à la fin :) 3 champs: heure, heure, date. et définissez mes champs précédents dans le modèle. Merci. – amrnt

Questions connexes