datetime_select的多参数错误

时间:2011-01-17 10:08:49

标签: ruby-on-rails postgresql

我的表格中有以下代码。

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

任何人都知道为什么会这样吗?

在这个link似乎有一个“脏”修复,但也许在Rails 3中有更好的解决方案?

6 个答案:

答案 0 :(得分:4)

基督教。这是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方法几乎一无所知,所以你应该对它进行自己的阅读,但我所知道的是,它为给定的实例变量创建了一个读者和一个编写者,更重要的是, setter接受多参数属性。我如何选择选项:

class_name:我们期望的类的名称。在这种情况下,Time
mapping:第一个参数是类,第二个参数似乎适用于类的实例响应的任何方法。我选择to_s 构造函数:不确定这是如何工作的。似乎在@my_timenil时被调用 转换器:不确定这应该如何工作。似乎是从my_time =调用,但似乎没有应用质量分配。 我遇到这个问题的一个问题是,时间是以UTC而不是环境的时区设置的。所以不幸的是我们不能直接使用my_time,而是需要将其转换为适当的时区:

Time.zone.parse(my_time.to_s(:number))

答案 1 :(得分:1)

What Does ActiveRecord::MultiparameterAssignmentErrors Mean?

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

答案 2 :(得分:0)

使用没有数据库属性支持的日期下拉列表时遇到了同样的问题。我写了一个小的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

答案 3 :(得分:0)

我在下面的模型中面临同样的问题

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

希望这很有用

答案 4 :(得分:-1)

从代码中删除: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 %>

...谢谢

答案 5 :(得分:-5)

我遇到了同样的问题。 我刚为该属性添加了 attr_accessible ,它运行正常。

希望它有所帮助。