Reputation: 5193
I have a form with a time_select and a jquery datepicker,
I want to be able when I submit the form to merge the values of the time_Select and the datepicker into one datetime of my ActiveRecord model ...
Is there an elegant way to do that ? Should I do it client or server side ... I'd like to keep my action as simple as that :
def create
@drive = Drive.new(params[:drive]))
if @drive.save
flash[:notice] = 'Drive created !'
render :action => :show
else
render :action => :new
end
end
I don't know ... should I do it with virtual attributes in the model and merge them before_save or maybe in javascript when the form is submit or maybe you have a better idea ... What do you think ??
Thanks,
Mike.
Upvotes: 1
Views: 1104
Reputation: 23450
The short answer is: It doesn't matter, they're equally good.
You have 3 reasonable places you could handle this.
Regardless of what method you use, you will have to process the data in the controller/model because all parameters are received as strings.
In the model and controller variants you have an extra decision to make. Piece together the DateTime from 6 fields or use a pair of strings (one containing the value, one containing the strptime format.)
Knowing that DateTime's constructor methods require about the same amount of work to build a datetime object from set of separate fields as it does to build the object from a datetime string and a format string. It really doesn't matter how you build the DateTime object.
So it all boils down to a matter of personal preference.
Personally I believe this logic belongs in the model. I wouldn't put it in the javavascript because I like to ensure that my code doesn't break if Javascript is disabled. The controller is an equally good fit. But I feel offloading this logic to the model allows for more robust handling of dates and validations. I also find the strptime constructor much easier to read than the 7 argument civil constructor. But the civil constructor doesn't require me to ensure format hours/minutes/seconds are exactly 2 digits long. Either way I would be passing year, month, day, hour, minute and second offset as separate attr_accessors fields, so I that data available for processing if necessary.
Example code
class Drive < ActiveRecord::Base
...
attr_accessor :year, :month, :day, :hour, :minute, :second, :locale_offset
before_validation :build_date
validates :future_time
def build_date
begin
self.date = DateTime.civil( year.to_, month.to_i, day.to_i,
hour.to_i, minute.to_i, second.to_i, user.locale_offset)
rescue
errors.add(:date, "Invalid date")
return false
end
end
def future_time
unless date > DateTime.now
errors.add(:date, "Date occurs in the past.")
end
end
end
Upvotes: 3