многопараметрическая ошибка с datetime_select - PullRequest
9 голосов
/ 17 января 2011

У меня есть следующий код в моей форме.

<%= f.datetime_select(:date_time, :prompt => {:day => 'Day', :month => 'Month', :year => 'Year'}, :start_year => Date.today.year, :end_year => Date.today.year + 2, :minute_step => 15, :include_blank => false) %> if either one is blank.

Когда одно из полей остается пустым, Я получаю:

1 error(s) on assignment of multiparameter attributes

Параметрыпередаются:

{"utf8"=>"✓",
 "authenticity_token"=>"kQpfsj5RxnDtxkvBdwPEFnX1fY6euKnMQeDRAkvJvIE=",
 "event"=>{"description"=>"",
 "venue"=>"",
 "street"=>"",
 "city"=>"",
 "country_id"=>"",
 "date_time(1i)"=>"",
 "date_time(2i)"=>"",
 "date_time(3i)"=>"",
 "date_time(4i)"=>"00",
 "date_time(5i)"=>"00",
 "ticket_url"=>""},
 "x"=>"94",
 "y"=>"12"}

Кто-нибудь знает, почему это происходит?

В этой ссылке , кажется, есть "грязное" исправление, но, возможно, в Rails 3 есть лучшее решение?

Ответы [ 6 ]

4 голосов
/ 22 февраля 2011

Christian. Это ошибка в Rails, которая проверяет базу данных, чтобы определить тип, необходимый для многопараметрических атрибутов. Я предполагаю, что ваш атрибут date_time не связан со столбцом времени в вашей базе данных.

Недавно я решил эту проблему, когда хотел, чтобы атрибут, не относящийся к базе данных, принимал многопараметрические атрибуты, это было лучшее решение, которое я мог придумать:

Я обнаружил, что хочу установить attr_accessor для обработки передачи даты моей модели в теге form_for с помощником f.datetime_select. Итак, вот что у меня было:

Модель:

attr_accessor :my_time

Вид:

<%= f.datetime_select :my_time %>

К сожалению, когда я отправляю свою форму, я получаю это:

1 error(s) on assignment of multiparameter attributes

Что ж, получается, что это на самом деле ошибка Rails, билет на которую был отправлен. В то же время, как мы делаем эту работу? Единственное решение, которое я смог найти, которое было привлекательным для удаленного использования, - это использование composed_of вместо attr_accessor. так что ...

Модель:

  composed_of :my_time,
              :class_name => 'Time',
              :mapping => %w(Time to_s),
              :constructor => Proc.new{ |item| item },
              :converter => Proc.new{ |item| item }

Я почти ничего не знаю о методе composed_of, поэтому вам, вероятно, следует выполнить его собственное чтение, но я знаю, что он создает и средство чтения, и средство записи для данной переменной экземпляра, и, что более важно, средство установки принимает многопараметрические атрибуты. Как я выбрал варианты:

имя_класса: имя нашего ожидаемого класса. В этом случае Time
Отображение: первый аргумент является классом, а второй аргумент, похоже, работает с любым методом, на который отвечает экземпляр класса. Я выбрал to_s Конструктор: Не совсем уверен, как это должно работать. Кажется, вызывается, когда @my_time равно nil.
Конвертер: Не совсем уверен, как это должно работать. Кажется, вызывается когда из my_time =, но, кажется, не применяется с массовым назначением. Одна из проблем, с которой я столкнулся в этом решении, заключалась в том, что время устанавливалось в UTC, а не в часовом поясе среды. Так что, к сожалению, мы не можем использовать my_time напрямую, но вместо этого нужно преобразовать его в соответствующий часовой пояс:

Time.zone.parse(my_time.to_s(:number))
1 голос
/ 15 июля 2012

Что означает ActiveRecord :: MultiparameterAssignmentErrors?

def initialize(attributes={})
  date_hack(attributes, "deliver_date")
  super(attributes)
end   

def date_hack(attributes, property)
  keys, values = [], []
  attributes.each_key {|k| keys << k if k =~ /#{property}/ }.sort
  keys.each { |k| values << attributes[k]; attributes.delete(k); }
  attributes[property] = values.join("-")
end
0 голосов
/ 26 января 2014

Я столкнулся с той же проблемой с моделью ниже

class Reservation < ActiveRecord::Base
    attr_accessor :sid, :check_in, :credit_card_number, :expiration_date
    attr_accessible :expiration_date
end

Соответствующая форма с полем для срока годности:

<div class="field">
  <%= f.label :expiration_date %>
  <%= f.date_select(:expiration_date, start_year: Time.now.year + 3, :end_year => Time.now.year - 3, discard_day: true) %>
</div>

как упомянул @gabeodess, проблема заключается в проверке базы данных на предмет вывода типа в соответствии с решением, которое я сделал для этого, добавив следующий код в модель, чтобы указать тип необходимого атрибута в этом случае: expiration_date, чтобы модель изменено, чтобы быть следующим

class Reservation < ActiveRecord::Base
  attr_accessor :sid, :check_in, :credit_card_number, :expiration_date
  attr_accessible :expiration_date
  columns_hash["expiration_date"] = ActiveRecord::ConnectionAdapters::Column.new("expiration_date", nil, "date")
end

Надеюсь, это полезно

0 голосов
/ 10 июня 2012

У меня была та же проблема с использованием раскрывающегося списка дат, который не был поддержан атрибутом базы данных.Я написал небольшое промежуточное ПО Rack, чтобы справиться с проблемой:

class DateParamsParser
  def initialize(app)
    @app = app
  end

  def call(env)
    if %w{POST PUT}.include? env['REQUEST_METHOD']
      params = Rack::Utils.parse_query(env["rack.input"].read, "&")

      # selects only relevant params like 'date1(1i)'
      filtered_params = params.select{ |key, value| key =~ /\(\di\)/ }
      # delete date params
      filtered_params.each { |key, value| params.delete(key) }

      # returns something like {'date1' => [2012, 5, 14], 'date2' => [2002, 3, 28]}
      date_array_params = filtered_params.sort.reduce({}) do |array_params, keyvalue|
        date_key = keyvalue.first.match(/(.+)\(/)[1] + ']'
        array_params[date_key] ||= []
        array_params[date_key] << keyvalue.last
        array_params
      end

      # Creates params with date strings like {'date1' => '2012-5-14', 'date2' => '2002-3-28'}
      date_params = Hash[date_array_params.map{ |key, date_array| [key, date_array.join('-')] }]

      params.merge! date_params
      env["rack.input"] = StringIO.new(Rack::Utils.build_query(params))
      env["rack.input"].rewind
    end

    @app.call(env)
  end
end

И в application.rb я поместил

config.middleware.insert_before ActionDispatch::ParamsParser, "DateParamsParser"

Обратите внимание, что здесь я строю только строку даты.Поэтому, если вам также требуется время, вам нужно построить date_params по-другому.

0 голосов
/ 27 ноября 2011

Я столкнулся с той же проблемой. Я только что добавил attr_accessible для этого атрибута, и он отлично работает.

Надеюсь, это поможет.

0 голосов
/ 17 января 2011

Удалите :include_blank => false из вашего кода.

<%= f.datetime_select(:date_time, :prompt => {:day => 'Day', :month => 'Month', :year => 'Year'}, :start_year => Date.today.year, :end_year => Date.today.year + 2, :minute_step => 15 %>

Спасибо ....

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