Меню Multi Select и виртуальные атрибуты - PullRequest
0 голосов
/ 11 марта 2010

У меня есть таблица периодов, в которой есть start_at: datetime end_at: datetime. Поскольку каждый период начинается и заканчивается в одну и ту же дату, я хочу отделить три поля вместо двух.

поле 1: дата поле 2: время «00:00» старта поле 3: время «00:00» конца

Я начал и сделал это. Но, к сожалению, я столкнулся с проблемой.

Поэтому, пожалуйста, посмотрите на модель периода, форму и ошибку, и исправьте меня, исправьте код.

Заранее спасибо!

Модель периода

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

Схема периодов

#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>

Ошибка

==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"}

1 Ответ

3 голосов
/ 11 марта 2010

помощники формы даты и времени , включенные в ActionView, генерируют специальные элементы формы, которые используют так называемое «многопараметрическое назначение». Это означает, что когда вы отправляете поля формы date_select, datetime_select или time_select, они генерируют несколько отдельных параметров, которые скомпилированы ActiveRecord в один объект даты, даты и времени. В вашем случае эти параметры выглядят так:

 "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"

Я должен отметить, что они очень отличаются от строк, которые вы ожидаете в методах start_at_time= и end_at_time= вашей модели Period, и что ваша модель вообще не имеет метода show_date=.

Этот формат параметра с круглыми скобками - это то, что Rails использует для многопараметрического присваивания. Однако ActiveRecord опирается на соответствующий столбец базы данных, чтобы узнать, представляют ли несколько представленных параметров объект даты, времени или даты и времени. Это означает, что помощники не будут работать с виртуальными атрибутами, по крайней мере, из коробки. Нет никакого способа сказать, какой объект они ожидают.

На это есть хотя бы один активный билет:

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

И по этой ссылке вы можете найти отличный обзор многопараметрического назначения и использования помощников в форме даты с Rails:

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

Что касается общего улучшения этой схемы: если каждый период начинается и заканчивается в одну и ту же дату, почему бы не использовать атрибут date для хранения даты периода и два атрибута time для хранения времени начала и окончания. Вы можете легко создать методы, которые возвращают объекты start_at и end_at datetime, скомпилированные из этих атрибутов.

Вы можете настроить свою форму с помощью помощников формы более или менее, как вы уже сделали. Вы также можете легко настроить проверку для атрибута end_time, гарантируя, что он всегда будет позже, чем start_time.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...