【问题标题】:"error(s) on assignment of multiparameter attributes" date/time fields“多参数属性分配错误”日期/时间字段
【发布时间】:2013-09-21 10:27:15
【问题描述】:

我的应用程序有一个模型“约会”,它有一个开始和结束属性,它们都是日期时间。我正在尝试将日期和时间部分与我的表单分开设置,以便我可以使用单独的日期和时间选择器。我想我应该能够做到这一点。从我读过的内容来看,rails 应该将这两个部分组合起来,然后像通常那样将组合字段解析为日期时间 我得到的错误:

2 error(s) on assignment of multiparameter attributes [error on assignment ["2013-09-16", "15:30"] to start (Missing Parameter - start(3)),error on assignment ["2013-09-16", "16:30"] to end (Missing Parameter - end(3))]

这些是请求参数:

{"utf8"=>"✓", "authenticity_token"=>"OtFaIqpHQFnnphmBmDAcannq5Q9GizwqvvwyJffG6Nk=", "appointment"=>{"patient_id"=>"1", "provider_id"=>"1", "start(1s)"=>"2013-09-16", "start(2s)"=>"15:30", "end(1s)"=>"2013-09-16", "end(2s)"=>"16:30", "status"=>"Confirmed"}, "commit"=>"Create Appointment", "action"=>"create", "controller"=>"appointments"}

我的模特

class Appointment < ActiveRecord::Base
    belongs_to :patient
    belongs_to :practice
    belongs_to :provider
  validates_associated :patient, :practice, :provider


end

以及视图的相关部分:(它是一个简单的形式)

      <%= f.input :"start(1s)", :as => :string, :input_html => { :class => 'date_time_picker' , :value => Date.parse(params[:start]) }%>
      <%= f.input :"start(2s)", :as => :string, :input_html => { :class => 'date_time_picker' , :value => Time.parse(params[:start]).strftime('%R') }%>

      <%= f.input :"end(1s)", :as => :string, :input_html => { :class => 'date_time_picker' , :value => Date.parse(params[:end]) }%>
      <%= f.input :"end(2s)", :as => :string, :input_html => { :class => 'date_time_picker' , :value => Time.parse(params[:end]).strftime('%R') }%>

更新: 这就是我的模型现在的样子,我一直在尝试做 getter/setter 方法,但我被卡住了,因为模型中的 start-dat、start_time 等都是 nil 并且参数没有通过发送

class Appointment < ActiveRecord::Base
    belongs_to :patient
    belongs_to :practice
    belongs_to :provider
    validates_associated :patient, :practice, :provider
    before_validation :make_start, :make_end


    ############ Getter Methods for start/end date/time
    def start_time
        return start.strftime("%X") if start
    end

    def end_time
        return self.end.strftime("%X") if self.end
    end

    def start_date
        return start.strftime("%x") if start
    end

    def end_date
        return self.end.strftime("%x") if self.end
    end


    def start_time=(time)
    end

    def end_time=(time)
    end

    def start_date=(date)
    end

    def end_date=(date)
    end


    def make_start
        if defined?(start_date)
            self.start = DateTime.parse( self.start_date + " " + self.start_time)
        end
    end

    def make_end
        if defined?(end_date)
            self.start = DateTime.parse( end_date + " " + end_time)
        end
    end
end

【问题讨论】:

  • 嗨。你能解决这个问题吗?

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

How do ruby on rails multi parameter attributes *really* work (datetime_select)

根据这个问题,多参数属性方法适用于Date,但不适用于DateTime 对象。在Date 的情况下,您将传递年、月和日作为单独的值,因此Missing Parameter - start(3),因为预期的第三个参数不存在。

DateTime,然而,至少需要五个参数来实例化DateTime.new(2013, 09, 16, 15, 30),所以在你的情况下你不能依赖自动解析。您必须先拆分参数,在这种情况下,您可以轻松地自己解析它,然后使用 before_filter 或类似方法保存对象。

查看构造函数: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/DateTime.html#method-c-new

和多参数描述: http://apidock.com/rails/ActiveRecord/AttributeAssignment/assign_multiparameter_attributes

【讨论】:

  • 我已经更新了我的模型并试图转移到 getter setter 方法,但我仍然做错了什么!
【解决方案2】:

你想模仿 #date_select 吗?如果是,请参阅答案的第二部分。

日期数据库类型转换

如果要将 DateTime 分配给数据库,则它必须是 DateTime 对象。这里使用了一个字符串数组,["2013-09-16", "15:30"]

您可以使用正则表达式从这些字符串中轻松计算日期时间:

/(?<year>\d+)-(?<month>\d+)-(?<day>\d+)/ =~ params[ 'start(1s)' ]
/(?<hours>\d+):(?<minutes>\d+)/ =~ params[ 'start(2s)' ]
datetime = DateTime.new( year.to_i, month.to_i, day.to_i, hours.to_i, minutes.to_i )

这会将年、月、日、小时和分钟存储在局部变量中,并基于它创建一个新的数据时间,然后您可以将其分配给您的模型。

然而,数据库不能按原样存储 ruby​​ DateTime 实例,因此在后台,rails 在保存日期或日期时间字段以将其转换为字符串时会进行转换。使用的方法是#to_s(:db),例如:

DateTime.now.to_s(:db)     # => "2013-09-17 09:41:04"
Time.now.to_date.to_s(:db) # => "2013-09-17"

所以理论上你可以简单地加入你的字符串以获得正确的日期表示,但这不是一个好主意,因为:

  1. 这是实现细节,没有什么说这个日期格式在下一个 Rails 版本中不会改变
  2. 如果您在分配日期时间之后和保存之前尝试使用它(例如,在 before_save 中),它将是一个字符串而不是日期时间

使用 active_record 日期时间助手

因为一直这样做会很痛苦,所以 rails 有帮助程序来创建和使用日期时间表单输入。

FormBuilder#datetime_select 将只获取您想要的属性并构建所有需要的输入:

<%= f.datetime_select :start %>

这实际上会创建 5 个输入,分别命名为“start(1i)”(年)、“start(2i)”(月)、“start(3i)”(日)、“start(4i)”(小时) 和“start(5i)”(分钟)。

如果感觉很熟悉,那是因为这是我们在此答案的第一部分中检索到的用于构建日期时间的确切数据。当您将哈希分配给具有这些确切键的数据时间字段时,它将使用它们的值构建一个日期时间对象,就像我们在第一部分中所做的那样。

您自己的代码中的问题是您刚刚提供了“start(1i)”和“start(2i)”。 Rails 不明白,因为您只传递了年份和月份,比计算日期时间所需的要少得多。

【讨论】:

  • Olivier 我已经更新了我的模型并试图转移到 getter setter 方法,但我仍然做错了什么!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2016-09-30
  • 1970-01-01
  • 2022-01-01
  • 2013-04-29
  • 2012-11-07
  • 1970-01-01
相关资源
最近更新 更多