Rails - how to validate one field against another for dates - ruby-on-rails

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.

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.

Rails - how to set default on edit form for a year select form

In my app, I let people select their start year for a job. This works fine when creating a new job, but on the edit form I want the year the user selected during create to be automatically population.
My code:
<%= select_year Date.today, start_year: Time.now.year, end_year: Time.now.year - 95, field_name: :start, prefix: :job %>
Currently, it just defaults to 2013 everytime. I know I am passing in the instance variable correctly because the other fields are populated automatically, just not this year dropdown.
How do I get this to work?
This answer was too long to put in the comments, so I'm putting it here as an answer, but let me know if it answers your question or not.
You could manually set the start_year and end_year variables to, for example, 1950 and Time.now.year. Then, set the first argument in select_year helper to the instance variable to make it the default selection between the wide range instead of Date.today.
For example:
<%= select_year #instance_variable, start_year: 1950, end_year: Time.now.year, field_name: :start, prefix: :job %>
More examples are available in the Rails Docs, too:
http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-select_year

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) %>.

Scaffolding A model with an attribute of type datetime creates a 10 years range in the form

For a simple rails application ( 1.86 /2.3.5) , lets say I run a simple scaffold
script/generate scaffold blog title:string content:text published:date
When I open up the new / edit view for the blog controller in index/new.html.erb , I see that the drop down enabler for date select has a date range of 2005 - 2015 , i.e 5 years +/-
I tried to change this default behavior by introducing this code
f.date_select :entered,
:start_year => 1970,
:end_year => 2020
Apparently this has no impact to the behavior mentioned above. How do I increase the date_select range which seems to be default?
This seems to be ok. Except did you put it inside the <%= %> ?
Edit: Also i noticed that you say your scaffold has published column whereas your date_select refers to the entered column.
As in, <%= f.date_select :published, :start_year => 1970, :end_year => 2020 %>
If that doesn't work you can also try,
<%= f.date_select :published, :start_year => Time.now.year - 40, :end_year => Time.now.year + 10 %>
I tried it and it works for me. Cheers! :)

Resources