Reputation: 1113
My table has a release_date column that saves in the format
2002-02-01
In the model I have
validates_date :release_date, :allow_blank => true
In my new view I have the following
<%= f.label :release_date, class: "control-label" %>
<%= f.date_select :release_date, :start_year => Date.current.year, :end_year => 1970, :include_blank => true %>
With gives three separate drop downs for selecting a date.
What I want is for a partial date to be selectable when a user only knows the year, or the month and the year. I thought this might work with the appropriate allow_blank tags in but it doesn't Currently if you select and month and year but leave the day blank it doesn't save the date to the db at all.
How can I allow for partial dates? Preferably saving with the same format as currently used so that my existing data isn't invalid.
In my show view I call release_date with this
<%= @miniature.release_date.strftime("%d %b %Y") unless @miniature.release_date.blank? %>
I would like to be able to display the whole date when available and if not have it appear as
Feb 2002
or just
2002
where that is all that's available.
Upvotes: 0
Views: 976
Reputation: 4538
I guess your release_date
should be a date
column, it means that a full-date is required for creating record even only the year or year+month are given.
You may need an integer column, date_mask
for example, to tell which parts(year, month, day) are available and modify the create
action in your controller to store date_mask
information.
class MyController < ApplicationController
def create
#...
if params[:my_model][:"release_date(2i)"] == ''
# no month is given, insert fake month and day
params[:my_model][:"release_date(2i)"] = '1'
params[:my_model][:"release_date(3i)"] = '1'
mask = 4 # 100
elsif params[:my_model][:"release_date(3i)"] == ''
# no day is given, insert a fake day
params[:my_model][:"release_date(3i)"] = '1'
mask = 6 # 110
else
# full-date
mask = 7 # 111
end
# ...
MyModel.create(my_model_params.merge(date_mask: mask))
# ...
end
private
def my_model_params
params.require(:my_model).permit(:release_date, :date_mask)
end
end
In your model, create a method release_date_display
to show the date according release_date
and date_mask
class MyModel < ActiveRecord::Base
#...
def release_date_display
if self.date_mask == 4
return self.release_date.strftime('%Y')
elsif self.date_mask == 6
return self.release_date.strftime('%b %Y')
else
return self.release_date.strftime('%F')
end
end
#...
end
For existing data, just insert 7 in your data_mask
column.
UPDATE:
An example to handle partial date: https://github.com/sibevin/partial-date-app
Upvotes: 4
Reputation: 4703
There are some gems out there to deal with this use case:
https://github.com/58bits/partial-date (this one uses a single column)
The other ones tend to use multiple columns:
https://github.com/gnapse/incomplete_date
https://github.com/alexreisner/flex_date
You'll also find more information in this SO thread: How would I store a date that can be partial (i.e. just the year, maybe the month too) and output it later with the same specifity?
Upvotes: 1