2

My application has a model "Appointments" which have a start and end attribute both which are datetimes. I am trying to set the date and time parts separately from my form so I can use a separate date and time picker. I thought I should be able to do it like this. From what I ahve read rails should combine the two parts and then parse the combined field as a datetime like it usually would The error I am getting:

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

These are the request parameters:

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

My Model

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


end

And the relevant part of the view: (its a simple form)

      <%= 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') }%>

UPDATE: THis is now how my model looks like, Ive been trying to do getter/setter methods but I am stuck because start-dat, start_time etc are nil in the model and the parameters aren't sent through

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
4

2 回答 2

2

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

日期数据库类型转换

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

您可以使用 regexps 从这些字符串中轻松计算日期时间:

/(?<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)”(小时)和“开始(5i)”(分钟)。

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

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

于 2013-09-17T07:57:48.033 回答
0

请参阅ruby​​ on rails 多参数属性如何*真正*工作 (datetime_select)

根据这个问题,多参数属性方法适用于Date但不适用于DateTime对象。在 a 的情况下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

于 2013-09-17T07:47:08.923 回答