datetime_select 的多参数错误

发布于 2024-10-12 12:28:12 字数 1021 浏览 3 评论 0原文

我的表单中有以下代码。

<%= 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 中有更好的解决方案?

I have the following code in my form.

<%= 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.

When one of the fields is left blank, I get:

1 error(s) on assignment of multiparameter attributes

The params that are being passed are:

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

Anyone know why this is occurring?

There seems to be a "dirty" fix for this at this link, but perhaps there is a better solution in Rails 3?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不如归去 2024-10-19 12:28:12

基督教。这是 Rails 中的一个错误,它会检查数据库以推断多参数属性所需的类型。我的猜测是您的“date_time”属性与数据库中的时间列没有关联。

我最近解决了这个问题,我想要一个非数据库属性来接受多参数属性,这是我能想到的最佳解决方案:

我发现自己想要设置一个 attr_accessor 来处理将日期传递给我的模型位于带有 f.datetime_select 帮助器的 form_for 标记中。所以这就是我所拥有的:

模型:

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:我们期望的类的名称。在本例中,时间
映射:第一个参数是类,第二个参数似乎适用于类实例响应的任何方法。我选择了to_s
构造函数:不太确定这是如何工作的。似乎是在 @my_timenil 时调用。
转换器:不太确定这是如何工作的。似乎是从 my_time= 调用的,但似乎不适用于批量分配。
我在使用此解决方案时遇到的一个问题是,时间是以 UTC 设置的,而不是环境的时区。因此不幸的是我们不能直接使用 my_time ,而是需要将其转换为正确的时区:

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

Christian. This is a bug in Rails that checks the database to infer the type needed for the multiparameter attributes. My guess is that your "date_time" attribute is not associated with a time column in your database.

I recently tackled this problem where I wanted a non-database attribute to accepted multiparameter attributes, this was the best solution I could come up with:

I found myself wanting to set an attr_accessor to handle passing a date to my model in a form_for tag with the f.datetime_select helper. So this is what I had:

Model:

attr_accessor :my_time

View:

<%= f.datetime_select :my_time %>

Unfortunately when I submit my form I get this:

1 error(s) on assignment of multiparameter attributes

Well it turns out that this is actually a Rails bug a ticket for which has been submitted. In the meantime how do we make this work? The only solution I could find that was remotely attractive was to make use of composed_of as a replacement for attr_accessor. so...

Model:

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

I know almost nothing about the composed_of method so you should probably do your own reading on it, but what I do know is that it creates both a reader and writer for the given instance variable, and more importantly, the setter accepts multiparameter attributes. How I chose the options:

class_name: the name of our expected class. In this case, Time
mapping: the first argument is the class and the second argument seems to work with any method that an instance of the class responds to. I chose to_s
constructor: Not really sure how this is supposed to work. Seems to be called when @my_time is nil.
converter: Not really sure how this is supposed to work. Seems to be called when from my_time=, but doesn't seem to be applied with mass assignment.
One problem I ran into with this solution was that times were getting set in UTC instead of the environment's time zone. So unfortunately we cannot use my_time directly, but instead need to convert it to the proper time zone:

Time.zone.parse(my_time.to_s(:number))
同展鸳鸯锦 2024-10-19 12:28:12

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

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
万劫不复 2024-10-19 12:28:12

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

Note,我在这里只构建了一个日期字符串。因此,如果您还需要时间,则需要以不同的方式构建 date_params

I had the same problem using a date dropdown that wasn't backed by a database attribute. I wrote a little Rack middleware to cope with the problem:

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

And in application.rb I put

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

Note that I only build a date string here. So if you also require time you'll need to build the date_params differently.

贪恋 2024-10-19 12:28:12

我在下面的模型中遇到了同样的问题

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

希望这很有用

I faced the same problem with the model below

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

The corresponding form with the field for the expiration date:

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

as mentioned by @gabeodess the problem is checking the database to infer the type accordingly the solution I did for it was adding the following code to the model to put the type of the needed attribute in this case :expiration_date so the model is modified to be the following

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

Hope this is useful

坏尐絯℡ 2024-10-19 12:28:12

删除 :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 %>

谢谢....

Remove :include_blank => false from your code.

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

Thanks....

絕版丫頭 2024-10-19 12:28:12

我面临着同样的问题。
我刚刚为该属性添加了 attr_accessible ,它工作正常。

希望有帮助。

I was facing the same problem.
I just added attr_accessible for that attribute and it works fine.

Hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文