In Rails, Convert string from date_select to Date - ruby-on-rails

I have a string like this:
{2=>1, 3=>1, 1=>2008}
It was generated from a select field like this:
<%= user_record.date_select :response, {
order: [:month, :day, :year],
prompt: {
day: 'Select day',
month: 'Select month',
year: 'Select year'
},
start_year: Date.today.year - 12,
end_year: Date.today.year - 110
} %>
And stored as a string in the database. (I can't change this to a date type, because it's user generated content).
This causes 2 problems:
I want to show a humanized version of the date on the Show view. Right now it looks like {2=>1, 3=>1, 1=>2008}
I want to show a date select input on the Edit View form field. Right now it errors with
undefined method `year' for "{2=>1, 3=>1, 1=>2008}":String
I have tried splitting the string, and stripping characters, but is there a better solution in Ruby?

You could add a customer setter and getter method to your model to translate between the incoming hash from the view and the string type database column.
Something like this might work:
def response
Date.parse(super)
end
def response=(value)
value = Date.new(value[1], value[2], value[3]) if value.is_a?(Hash)
super(value.to_s)
end

Related

How to set default date and include_blank in date_select in Rails

I'm using date_select in Rails 4 and I'd like to be able to have today's date as default but also allow for the user to leave the date field blank.
<%= f.date_select(:birthdate, {include_blank: true, default: Date.today.to_date, start_year: Date.today.year - 100, end_year: Date.today.year - 18}) %>
What is the best way to allow for blank as well as have today's date appear by default when the page opens?
The option you need is selected, i.e:
<%= f.date_select(:birthdate,
include_blank: true,
selected: Date.today, # substitute 18.years.ago to prefill year
start_year: Date.today.year - 100,
end_year: Date.today.year - 18) %>
The approved answer will overwrite the value already assigned to the birthdate every time you go to edit the record. See here.
If your model is, e.g., #student, and your form is form_for #student do |f|, this should work. It fails through to Date.current if #student.birthdate is empty.
<%= f.date_select(:birthdate,
include_blank: true,
selected: #student.birthdate || Date.current, # Date.current respects time_zones
start_year: Date.today.year - 100,
end_year: Date.today.year - 18) %>
However, be aware that the blank option will always be set to the current date when you go to edit the record, requiring the user to reset to blank if the data is unknown. This risks the insertion of bad data - arguably, less usable than having to choose the date to begin with.

use Rails date_select with Angular

How do you use Rails date_select form helper and generate a seperate ng-model for month and for year?
// Slim
= f.date_select :from, {
order: [:month, :year],
start_year: Time.now.year,
end_year: 1990,
include_blank: true },
{ :'ng-required' => 'isRequired'
}
The date_select makes it easy to set differenct prompts per each field. Is there any way to do this with your custom attributes?
date_select("article", "written_on", prompt: { day: 'Select day', month: 'Select month', year: 'Select year' })
The problem is that date_select creates 3 select_tag fields(one for month, year, and day). You can add the ng-model tag within html_options for date_select, but the problem is that all 3 select fields will have an identical ng-model tag with the same name. Angular doesn't like having multiple ng-model objects with the same name, and I don't know how to get around this. The solution I used was just to recreate what date_select does and create 3 select_tag fields. It's definitely not as elegant as the date_select field but it does work. I'd love to hear if anyone has a better solution!

Rails - how to validate one field against another for dates

I think this is a simple question. In my app, I have a model where users select a 'start' date and a 'stop' date when submitting a new record. The dates are only the years, excluding month and day.
I just want to write a validation to ensure that the stop date is greater than the start date, so you can't submit something that started in 2012 and ended in 2008. How would I do that?
My form fields are below:
<%= select_year Date.today, start_year: Time.now.year, end_year: Time.now.year - 95, field_name: :start %>
<%= select_year Date.today, start_year: Time.now.year, end_year: Time.now.year - 95, field_name: :stop %>
If you want to do a server side validation, you could add validation to your model
validate :stop_date
def stop_date
errors.add(:stop, "stop date cannot be older than start date") if stop < end
end
You could populate the errors on the view.

Three text fields for one database entry for rails

I currently have one text field for a date entry, I am trying to split the year, month and day up into three individual entries, seperated by '/'. The original text entry looks like:
<%= f.text_field :date, :placeholder => 'YYYY/MM/DD' %>
I would like to split this into three text_fields, and append them together, and put it into the date entry in the database.
How can I do this?
You often use textfields for dates because you then only needs one field. When you are having three different fields should you consider using select instead. Rails have a the date helper method date_select, so it would be somethink like this:
<%= f.date_select :date %>
This creates one select for years, one for months and one for days.
You can read more on http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-date_select
Add three virtual attributes to the model:
attr_accessor :form_month, :form_day, :form_year
Then put the following in the controller, not the model:
def create
# ...
form_date = [ params[:form][:form_month], \
params[:form][:form_day] ,
params[:form][:form_year] ].join("/")
#my_model.date = Date.parse(form_date)
# ... save and return ...
end
It would be a good idea to manually check each form parameter for validity. Date#parse may spit out the incorrect date if fed an incomplete date string.
Date.parse "2005/11/4"
# => Fri, 04 Nov 2005
Date.parse "/11/4"
# => Mon, 04 Nov 2013
Try to use https://github.com/plataformatec/simple_form
<%= f.input :deadline, :start_year => Date.today.year, :end_year => Date.today.year + 1, :order => [:day, :month, :year] %>
Do you have many options.

How to stop rails from including current day and month in date helper

I'm trying to use Rails date helpers with a form. However, I only want to get the year. I got the form code below from simple_form gem https://github.com/plataformatec/simple_form. The discard_day and discard_month prevent the month and day select box from showing. However, when I submit the form, I'm getting this multiparameter error
2 error(s) on assignment of multiparameter attributes
"start(1i)"=>"2013",
"start(2i)"=>"4",
"start(3i)"=>"23",
"end(1i)"=>"2011",
"end(2i)"=>"4",
"end(3i)"=>"23",
It appears Rails is just substituting the current day and month since none was entered in the form.
I'm wondering if there's a way to prevent Rails from including the current day and month, or am I supposed to deal with it in the controller. Right now, the create action looks like this
def create
#employment = current_user.employments.build(params[:employment])
if #employment.save
....
If I can't stop Rails from including the current day and month, then what would I do in the controller?
<%= f.input :start, as: :date, start_year: Date.today.year - 90,
end_year: Date.today.year, discard_day: true, discard_month: true %>
<%= f.input :end, as: :date, end_year: Date.today.year - 90,
end_year: Date.today.year, discard_day: true, discard_month: true %>
What is your data type for the start and end columns? If you are just storing a year, you can set them to an integer type instead of a date, and use <%= f.input :start, collection: (Date.today.year - 90)..(Date.today.year) %>.

Resources