How to add a date attribute in rails models - ruby-on-rails

Hi i'm a beginner in RoR and was having a little bit trouble in generating a particular model.
I want to create 2 models - List and Item. The List has_many Items and Item belongs_to List.
I want the Item model to have 3 attributes. rails g model Item name:string desc:string date:????
1.What data type to add for date:???
2.What format will the date attribute be in? (mm/dd/yy)?
3.And what kind of form input should it have?
f.date_field :date?
Thanks in advance!

1. What data type to add for date:???
In your migrations, you can use the following types for columns:
:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean
(extracted from the add_column transformation here)
In your case, if you don't need to store the time, you can use date:name_of_your_field.
2. What format will the date attribute be in? (mm/dd/yy)?
The attribute will be stored as a ActiveSupport::TimeWithZone, and you will have to format it when displaying it. You can use Time#strftime to do so.
your_attribute.strftime("%m/%d/%Y") #=> "11/19/2007"
3. And what kind of form input should it have?
Yes, you can perfectly use:
f.date_field :date?
It will return a text_field of type “date”. Depending on the browser support, a date picker will show up in the input field.
I hope that helps! Happy coding!

You can either have date or datetime according to the documentation. Therefore:
rails g model Item name:string desc:string date:datetime
or
rails g model Item name:string desc:string date:date
But the best practice is to use DateTime as a general purpose representation of time.
Although I would probably call it something more descriptive than date. (And just fyi created_at and updated_at columns are already created for you.)
The type is pretty much format agnostic. You can format it with strftime:
%Y%m%d => 20071119 Calendar date (basic)
%F => 2007-11-19 Calendar date (extended)
%Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
%Y => 2007 Calendar date, reduced accuracy, specific year
%C => 20 Calendar date, reduced accuracy, specific century
%Y%j => 2007323 Ordinal date (basic)
%Y-%j => 2007-323 Ordinal date (extended)
%GW%V%u => 2007W471 Week date (basic)
%G-W%V-%u => 2007-W47-1 Week date (extended)
%GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
%G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
%H%M%S => 083748 Local time (basic)
%T => 08:37:48 Local time (extended)
%H%M => 0837 Local time, reduced accuracy, specific minute (basic)
%H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
%H => 08 Local time, reduced accuracy, specific hour
%H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
%T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
%H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
%T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
%H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
%T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
%Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
%FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
%Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
%Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
%GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
%G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
%Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
%FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
%Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
%Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
%GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
%G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
Thanks to #BWStearns for that quote
Finally as far as input field goes: Have a look at these Form helpers.
<%= date_field(:user, :born_on) %>
<%= datetime_field(:user, :meeting_time) %>
<%= datetime_local_field(:user, :graduation_day) %>

Related

Sunspot - Searching in multiple date ranges

Here's my problem, I'll try to be concise.
I have a model Course that has_many Planning.
A Planning has a start_date and an end_date.
I want to retrieve (with sunspot) all the Courses that have a particular planning between a given start_date and an end_date.
The problem is that if I store in the model Course :
searchable do
date :start_date, multiple: true do
plannings.map(&:start_date)
end
date :end_date, multiple: true do
plannings.map(&:end_date)
end
...
end
I loose the fact that start_date and end_date are couples.
Is there a way / trick to store ranges?
Have almost the same problem, in my case start_date and end_date wasn't really a date, just a year (integer), solve it with multiple value fields as range:
searchable do
date :course_date, multiple: true do
plannings.map{|p| (p.start_date..p.end_date).to_a}
end
...
end
so course_date contain all years when courses going. If you have 2001-2003 and 2005-2007(2001, 2002, 2003, 2005, 2006, 2007) and search with equal_to.
A possibility would be to make your query in two times. First find the plannings, then find the courses restricting courses by ID.
Maybe not a very optimised one, but why try to optimize to soon...
Or to index hours with a function:
def happens_between_8_and_9
return true if start_date > 8..
end
searchable do
boolean :happens_between_8_and_9
boolean :happens_between_9_and_10
end
```

Repeatable Custom Schedule in Rails

I'm working on creating a Rails app that allows users to set availability Sunday through Saturday, with a start time, end time, and location (simple string). I have an User object and I'm unsure of how to continue. I know I could have a large set of Time objects like so:
class User
field :mondayStartTime, :type => Time
field :mondayEndTime, :type => Time
field :mondayLocation, :type => String
field :tuesdayStartTime, :type => Time
field :tuesdayEndTime, :type => Time
field :tuesdayLocation, :type => String
...
field :sundayEndTime, :type => Time
field :sundayLocation, :type => String
end
However, this seems terribly inefficient, though creating another unique object class seems just as bad and only results in more lines of code. Is there an easier way of implementing start/end times for a Sunday through Saturday schedule?
Thanks!
At first glance, I'd create an "Availability" model/class (or something less prone to misspelling like "Schedule") with the attributes of start_at, end_at, location, and day_of_week - and have that class belong to the User (and with the User having a "has_many :availabilities" or "has_many :schedules"). That seems (again at first glance) to be the most efficient and easiest to get the data back out - and you can use that separate class to do things like grouping schedules/availabilities together more easily.
Have you thought about creating objects for each day of the week, that have a start, end and location property?
Or perhaps, a Jobs object(model) that has fields for start time, end time, and location.
This way it would be possible to do, has_many :jobs and then you can either narrow down, by day, or select by a particular day. The narrowing down should be feasible with the ruby Time Class or ActiveSupport class (3.days.from_now, etc).
irb(main):001:0> require 'active_support/all'
=> true
irb(main):002:0> 2.days.ago
=> 2012-04-03 08:30:31 -0700
irb(main):003:0> 2.days.from_now
=> 2012-04-07 08:33:01 -0700
EDITED TO SHOW ACTIVE SUPPORT TIME CLASS

Rails output by date

I am trying to figure out the best way to display all records by date. I have a date_due column in my database that is a datetime field.
So my output would include every date for which there is an entry, like this:
April 1, 2011
- Buy tickets
- Pickup groceries
April 2, 2011
- Call client
I am trying to use the following method, which is not working: find_all_by_date_due
What's the easiest way to do this in Rails?
Railscasts has a nice cast on group_by :
http://railscasts.com/episodes/29-group-by-month
You could make the dates into an association and assign it an arbitrary ID through rails.
class Entry
belongs_to :date
end
class Date
has_many :entries
end
#entry.date.build(:date => 2011-02-01 20:23:22)
#entry.find_by_date(2)
Date.find(2).date
=> 2011-02-01 20:23:22

How to compare a string to dates in a find clause?

I want to get models whom date is within a date range.
So I want to do something like
MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { :date => nb_days_ago..Date.yesterday })
The thing is, the date attribute of my model is a string (with the format "08-24-2010"), and I can't modify this.
So to compare it to my range of dates, I tried this:
MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { Date.strptime(:date, "%m-%d-%Y") => nb_days_ago..Date.yesterday })
But I get an error that basically says that strptime can't process the :date symbol. I think my solution is not good.
How can I compare my string to my range of dates ?
Thanks
You have to convert the DB string to date in the database rather than in Ruby code:
Model.all(:conditions => [ "STR_TO_DATE(date,'%m-%d-%Y') BETWEEN ? AND ? ",
nb_days_ago, Date.yesterday])
Better solution is to normalize your model by adding a shadow field.
class Model
after_save :create_shadow_fields
def create_shadow_fields
self.date_fld = Date.strptime(self.date_str, "%m-%d-%Y")
end
end
Now your query can be written as follows:
Model.all(:conditions => {:date_fld => nb_days_ago..Date.yesterday})
Don't forget to add an index on the date_fld column.
Edit 1
For SQLLite, first solution can be rewritten as follows:
Model.all(:conditions => [ "STRFTIME('%m-%d-%Y', date) BETWEEN ? AND ? ",
nb_days_ago, Date.yesterday])
First of all I do not envy your situation. That's a pretty ugly date format. The only thing I can think of is to generate an array of strings, in that format, representing ALL the days between your starting date and your finish date, then use the SQL "IN" syntax to find dates in that set (which you can do from within ActiveRecord's :conditions param).
For example, if you wanted to search to 10 days ago:
num = 10 #number of days ago for search range
# range starts at 1 because you specified yesterday
matching_date_strings = (1..num).to_a.map{|x| x.days.ago.strftime("%m-%d-%Y")}
=> ["08-24-2010", "08-23-2010", "08-22-2010", "08-21-2010", "08-20-2010"]
# then...
records = MyModel.all(:conditions => { :date => matching_date_strings })
# or in your case with field1 and field2
records = MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { :date => matching_date_strings })
The idea is this should generate SQL with something like "... WHERE date IN ("08-24-2010", "08-23-2010", "08-22-2010", "08-21-2010", "08-20-2010")

rails datetime in separate fields

I may have over-complicated what I need to do but this is what I now have.
I have a jobs controller that has 2 fields
starts_at as DATETIME
end_time as DATETIME
I save the event_date in a form using a
calendar_date_select :starts_at ,:time => false
I save the date time as
time_select :starts_at, {:twelve_hour => true}
This saves the Event date i.e 12/26/2009 and the start time as 7:00 pm
I need to also save the event end_time without having to re-enter the date, just the time
time_select :end_time, {:twelve_hour => true}
If i just use the above, the time is correct but the date dafaults to 01/01/2000
How do I save the date with the same date from starts_at?
In your controller, if the :end_time is nil, set it to the :starts_at variable like so:
object.end_time = object.starts_at unless not object.end_time.nil?
You may be able to shorten the end to
object.end_time = object.starts_at unless object.end_time.present?
but I'm not sure which version of Rails you are using and what the default implementation of .present? does for dates.
You could do this in the model or controller, but isn't it possible that an event will start late at night and end on the following day? To allow for this possibility I'd recommend having two calendar_date_selects and auto-assigning the ending date when the starting date is chosen (so the second calendar_date_select will rarely be used).
If you really don't want two calendars, maybe use a hidden field for the ending date that follows the start date.
I wouldn't enforce this same-date rule below the interface level unless you're absolutely sure different start and end dates will never occur.

Resources