views:

245

answers:

3

I have a datetime column in a model and I want to display the form for this as separate text_fields for the time instead of the datetime_select helper drop down menus.

I know I will somehow have to validate and recreate the date to go back to the DB, but I am not sure how.

Should I use virtual attributes getter and setter methods? EG...

def virtual_minute=(minute)
  ...
end

def virtual_hour=(hour)
  ...
end

Or maybe in a callback?

A bit stucko!

+1  A: 

Virtual attributes are good IMO since they store the user data in an instance variable. Then in a before_save you construct a Time object assign it to the real variable.

nasmorn
+2  A: 

You don't need to write these yourself if you're using an ActiveRecord model. Multi-parameter attributes can be submitted via forms in pieces. As an example look at how the datetime_select method you're not too fond of works:

http://apidock.com/rails/ActionView/Helpers/DateHelper/datetime%5Fselect

Internally the various parameters get submitted with order and type information so that they can be properly encoded. You can build off of this functionality by simply naming your fields the same way. It is not too hard to copy a helper method you like and put the adjusted version in your ApplicationHelper module.

The values here show up as parameters named something along the lines of:

model_type[attribute(1i)]
model_type[attribute(2i)]
model_type[attribute(3i)]

These are combined in the correct order, converted as required, and submitted to a constructor for that attributes particular type, such as DateTime.

This avoids having to create your own wrapper methods.

In any case, the easy way to create attributes is to use the attr_accessor method, such as:

class MyModel < ActiveRecord::Base
  attr_accessor :some_date
end

That will create the appropriate accessor and mutator methods.

You can use a before_validation trigger to recombine the values in a single pass, or write a wrapper around the date retrieval method to reconsruct it as required.

tadman
Some valid points there.
Cameron
A: 

tadman, could you expand on the line "You can build off this functionality by naming your fields the same way."

My model has when:datetime for storing the user-entered date and time that an event should be scheduled for. I'm using a jQuery plugin that puts up a nice calendar for the year/month/day portion of the datetime.

So my trouble is in getting the hour and minute from time_select. The hour&minute gets passed back as when(5i) and doesn't get encoded into the year/month properly. By looking at the SQL Insert statement that got executed, I can see what gets encoded into when, but the hour the user chose has become the year and the month and day are 1 and 1.

My guess is that if I understood your comment I would need to supply (somehow) when(1i), when(2i) and when(3i) to the year/month/day jQuery selector, and when(4i), when(5i) to the time_select.

But all variations I've tried to do that have failed when the form layout tries to load.

Here's the view code:

<%= f.label "What date is the event?" %>
<%= f.text_field :when %>
<%= f.label "What time should recording begin?" %>
<%= time_select :request, :when, { :default => Time.now.change(:hour => 21), :simple_time_select => true, :minute_interval => 20, :time_separator => "" } %>

Here's the generated html:

<label for="request_What date is the event">What date is the event?</label>
<input id="request_when" name="request[when]" size="30" type="text" />
<label for="request_What time should recording begin">What time should recording begin?</label>
<select id="request_when_5i" name="request[when(5i)]">

< A Day Goes By With More Learning and Gnashing of Teeth >

I added three lines to my create action in my controller to rebuild the "when" attribute for my model, merging together the Y/M/D info with the HH:MM info --

foo = @request.when.to_datetime
bar = params[:request]["when(5i)"]

@request.when = Time.parse("#{foo.month}/#{foo.day}/#{foo.year} #{bar}")

Which was followed by the normal "if @request.save......."

This application is still a Rails 2.3.5 application

Jim