I have a calendaring application I am working on in Rails 3. I am gathering a 'to' and 'from' date from the user and creating a date, and creating events based on that range. Here is the code:
date_range = (params[:from_date]..params[:to_date]).to_a
date_range.each do |r|
params[:orientation][:class_date] = r
#orientation = Orientation.new(params[:orientation])
#orientation.save
end
This works like a charm. Now I want to add check boxes in the view for Monday - Friday so the user can specify which days the want a repeating event to be created for. My thinking is to expand on the logic above and create a date range with the 'to' and 'from' dates, then remove dates based on check boxes (days) the user checks. If the user checks 'Mon', 'Wed', 'Fri', I would create my date range, then remove all Thursday and Friday dates from the range. Can anyone suggest any methods in Ruby that might be handy for dealing with this?
You could add checkboxes in your form to ignore the selected date and then ignore each day in the loop:
# view
<% Date::DAYNAMES.each_with_index do |day_name, wday| %>
<%= check_box_tag "ignored_days[]", wday %>
<%= day_name %>
<% end %>
# controller
date_range.each do |r|
next if params[:ignored_days].include? r.wday.to_s #added edit here
params[:orientation][:class_date] = r
#orientation = Orientation.new(params[:orientation])
#orientation.save
end
Hope this helps!
Related
I want to implement a feature in Rails using the option of multiple checkbox. User must be able to choose the days in which he want the emails, like Monday, Tuesday, etc. This must be a list of checkboxes with day name as label and day index like 0 for Sunday, 1 for Monday, like that.
Also these fields must be checked when the user next time come here to edit.
I don't want to create separate db field for each day. This can be an array of day index stored in one database field. I am using Rails version 4.
Date::DAYNAMES will give the list of week days. Date::DAYNAMES.each_with_index will give the list of days with its index. I want to know the best way to implement the same.
Try this,
<%=select_tag 'days[]', options_for_select(Date::DAYNAMES.zip((0..6).to_a),
[selected days array goes here]
), :multiple => true%>
For using checkbox
<ul>
<% Date::DAYNAMES.zip((0..6).to_a).each do |day| %>
<li>
<%= check_box_tag 'days[]', day[1], [selected days array].include?(day[1]) -%>
<%= h day[0] -%>
</li>
<% end %>
</ul>
Hope it's help you.
I am working with a Calendar and I think that calendar deals only with date without a time.
Note: requested_date is a DateTime Attribute. I want to get all reservations with requested date and covert it to date only:
users_controller.rb
def myprofile
#reservation = Reservation.all
#resv_by_date = #reservation.group_by(&:requested_date) <-- make requested_date to date only
end
myprofile.html.erb
<div id="admin">
<%= calendar do |date| %>
<%= date.day %><br>
<% #resv_by_date.each do |reservation| %>
<%= reservation.requested_date.to_date %><br>
<% end %>
<% end %>
</div>
(this month 'May') requested_date is existing on my database
image output after the solution of the 1st answer
I don't think you want to use a group on your ActiveRecord relation not group_by which is a Ruby method.
Also, the method to get a Date from a DateTime object is datetime.to_date:
#reservations_by_date = Reservation.select(:requested_date).group(:requested_date)
#reservations_by_date.each { |reservation| puts reservation.requested_date.to_date }
Normally I'd advice you to try to group the data in the DB already (using group) for performance reasons instead of ruby code (group_by). But in your specific case it seems that you indeed need to retrieve all reservations in the given time period (e.g. month) and just group them by the date so that you can display all of them in the calendar view. In that case, you indeed have to group in ruby code.
You can do that simply by updating the block in group_by:
#reservations_by_date = Reservation.all.group_by { |res| res.requested_date.to_date }
Note that most probably you'll want to narrow down the select only to the given time period (e.g. the displayed month) first, using where conditions, I skipped that part from this answer.
The grouping above will create a hash of the reservations where the keys will be the dates (not datetimes) and the values will be arrays of reservations in the given date. In the calendar view, you can simply browse once you've accessed them using the date key:
<% calendar do |date| %>
<%= date.day %><br>
<% #reservations_by_date[date].each do |reservation| %>
<%= reservation.name ... or whatever %><br>
<% end %>
I am creating a scheduling app in Rails and I am getting stuck while trying to organize the rooms by date. When I say a room, I essentially just mean a block in the schedule. A typical event might have a lunch (one room), then a networking section (another room). Here is how I am getting the rooms:
#rooms = Room.where(event_id: #current_event.id).order(:start_time)
So that returns the rooms that belong to an event, in order of the start time. In my view I loop through and display the rooms for the event, but I want to group them in the view by the date in case there is an event that is on multiple days.
Also :start_time is a datetime type in Ruby. In human speak, what I would do is look at the date portion and if the room date is not the same as the current group, I would print the new date and continue to group the rooms that fall on that day. Here is a trivial example in case I am not being clear:
Event: Staff Retreat
July 14th, 2015
-----------------------
12:30 PM
Team building Lunch Begins
------------------------
6:30 PM
Team building Dinner Begins
------------------------
July 15th, 2015
------------------------
9:30 AM
Team building Breakfast Begins
So having the grouping of rooms in the #rooms variable that is a datetime, what would be the best way to display a table like the above? I would think that in my loop I should check if the date was the same as the previous room, and if not print the date
- #rooms.each do |room|
room.start_time.strftime("%B %d, %Y")
room.start_time.strftime("%I:%M%p")
room.name
I am having trouble with the logistics because with the Model-View-Controller concept, I feel that sorting in the view may have the view do something it shouldn't have to. I am also struggling with how to do that in the view. I would think setting a variable in the controller that would hold the temporary date as I loop through would work, but it seems like that would start to get pretty messy though. What is the best way to group the various dates from the #rooms variable?
Can you try this. this will return you a hash where date is the key and value will contain all the #rooms related to that time.
#rooms = Room.where(event_id: #current_event.id)
#rooms = Hash[#rooms.sort_by{|o| o.start_time.to_date}.group_by {|room| room.start_time.to_date}.map{|l,m| [l, m.sort_by{|k| k.start_time}]}]
now you can traverse the rooms like this in the views. im putting code in erb format.
<% #rooms.each do |k, v| %>
<%= k %>
<% v.each do |room| %>
<%= room.created_at.start_time('%I:%M %p')%>
<%= #room.name or title what so ever. %>
<% end %>
<% end %>
I'm using a date select in a rails 3 form.
<%=f.date_select :date %>
I would like to restrict the dates so that you can only pick dates that fall on a Sunday. Is there any way of going about doing this?
I'm also trying to stop dates which have already passed from appearing.
Thanks for any help in advance!
Rails date_select field generates three dropdown to select the parts of the date. There is no chanche, that you modify for example the month, and the day will still be sunday.
You must write some js magic to enforce such a role, or find an already existing datepicker and limit it. Or alternatively, you let the user to select a week, and calculate the exact date of sunday from that.
Ok having studied this out a bit further I don't think this is possible due to the format of the date_select field. The closest I can get is
<%=f.date_select :date, start_year: Time.now.year %>
so that at least you can't select dates from previous years. I've implemented the restriction on days and months that have past by setting up the view to automatically delete records that aren't relevant:
<% if(service.date < Date.today) %>
<% service.destroy %>
<% end %>
Not perfect but does the job in my case.
I've got an application that uses a calendar, and I'd like to provide a calendar summary on login. The summary should be formatted so it shows events for Today, Tomorrow, and This Week, like this:
Events For:
Today
Event 1
Tomorrow
Event 2
Event 3
Event 4
This Week
Event 5
Event 6
Event 7
Event 8
How do I render the partials so that they are grouped together in the right way, based on their date?
First one could add a model method for_dates(start_date,end_date) which would contain:
where([:date_column >= ? and :date_column <= ?, start_date, end_date])
Then use:
Model.for_dates(Date.today, Date.today)
Model.for_dates(Date.today+1, Date.today+1)
Default 'week' is Sunday to Monday. Add an offset if you wish different days, e.g.
Monday to Friday is
Model.for_dates(Date.today.beginning_of_week+1, Date.today.end_of_week+1)
Supposing your model is called Event and it has a date attribute, and your collection of these is called #events, here's one idea: Put this in your view...
<ul>
<%= render #events, locals: { events: #events } %>
</ul>
...then you would have a partial called _event.html.erb that looks like this:
<% last_event = event_counter == 0 ? nil : events[event_counter - 1]
next_event = events[event_counter + 1]
%>
<% if last_event && last_event.date != event.date
# add a new date header and start a new nested list of events
%>
<li><h3><%= event.date %></h3>
<ul>
<% end %>
<li><%= link_to event %></li>
<% if next_event && next_event.date != event.date
# end the nested list and make way for the next date header and set of events
%>
</ul>
</li>
<% end %>
What's happing is in the render call we're passing in the whole #events collection as a local called events. Then inside the partial we use the automatically-generated event_counter method to look up the previous (events[event_counter - 1]) and next (events[event_counter + 1]) events in the collection. Then if the date of the current event is different from the date of last_event (meaning it's the first one for that date) we start a new set with a new date heading, and if the date of event is different from the date of next_event (i.e. it's the last one for that date) we end the set.
It's a little ugly, and there are more elegant ways to do it for sure, but it gets the job done.