To me, this seems like a problem for the controller to solve. The model is still valid and would work fine if it were receiving its attributes in the "Rails" way. My solution involves the controller modifying the params
hash so that the model isn't even aware of the changes in the view. This depends on behavior in ActiveRecord that could be considered a private API, so…fair warning :-)
Say you have this model:
# app/models/example.rb
class Example < ActiveRecord::Base
attr_accessible :started_at # this is a DateTime
end
Adjust your view to use a normal text_field_tag
for the date portion (which will be enhanced by bootstrap-datepicker) and Rails's time_select
for the time portion:
# app/views/examples/_form.html.erb
<%= form_for(@example) do |f| %>
<p>
<%= f.label :started_at %>
<%= text_field_tag :started_at, @example.started_at.try(:to_date) %>
<%= f.time_select :started_at, :ignore_date => true %>
</p>
<p><%= f.submit %></p>
<% end %>
Notice that we're using try
since this form will be rendered for new and persisted records. This avoids problems when the started_at
attribute is nil
.
Then create a before_filter
in the controller to modify the params
hash before it gets sent to the model:
class ExamplesController < ApplicationController
before_filter :fix_params, :only => [:create, :update]
# ...
private
def fix_params
date = Date.parse(params.delete(:started_at))
params[:example].merge!({
'started_at(1i)' => date.year.to_s,
'started_at(2i)' => date.month.to_s,
'started_at(3i)' => date.day.to_s
})
end
end
Essentially, we're parsing params[:started_at]
as a date and assigning it to the correct keys of params[:example]
. Then when the parameters are eventually passed to the model, ActiveRecord will assign the model's started_at
attribute correctly.
You'll want to do some error checking and validation, but this should work for you.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…