Organizing by rails datetime in view - ruby-on-rails

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

Related

Multiple days of week in one attribute in database

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.

Rails how to display the earliest year (value) of the programs that the user belongs to?

I have a program table that belongs_to userprofile and userprofile table that has_many programs. The program has a program_year column and I wanted to display just the earliest year (value in that program_year) out of the programs if the user has multiple programs that he/she belongs to.
I have looked for similar questions and answers (How to get earliest and latest dates for associated objects). But can't seem to get my display working properly.
Having trouble understanding how to get the minimum program_year from programs for each userprofile. The code I have now..just gives me the minimum program_year of the current user and since it is in a loop. It displays the year x amount of times.
members_controller.rb
def index
#userprofiles = Userprofile.all
# the use of current_user is incorrect..
#member_program = Uprogram.where(:userprofile_id => current_user.userprofile.id).all
#member_since = #member_program.min
end
index.html.erb
<% f.uprograms.each do |program| %>
<% if program.present? %>
<!-- just want to display the lowest program_year value)
Member since: <%= program.program_year %>
<%= #member_since.program_year %>
<% end %>
<% end %>
Any insight would help! Thank you.
Couple of ideas:
1- This will get you only the earliest program_year among all the user programs:
Uprogram.where(userprofile_id: current_user.userprofile.id).order(: program_year).limit(1).pluck(:program_year).first
2- This will give you the earliest Uprogram object:
current_user.userprofile.programs.order(:program_year).limit(1).first

How do I add an attribute to an instance variable in rails 4?

Using Rails 4, in a controller I would like to add an attribute to an instance variable.
Sorry for the poor example, I'm trying to keep it simple.
E.g. In a controller, I create a new instance variable by looking up some users named John. Now, in my controller, I would like to sum up all the ages for all Users named John, put that summed age back in to the instance variable so it is available to the view.
The User model has attributes 'id', 'name' and 'age'.
#foo_users = Users.where(name: 'John')
#foo_users.each do |foo|
#foo_users.age_sum = Users.where(name: 'John').sum(:age) <-- this does not work
end
I have no need to save that summed age back to a database, since I will only use it in one view. I would like to be able to display all the users:
<% #foo_users.each do |user| %>
User name: <%= user.name =>
Sum of ages: <%= user.age_sum %>
<% end %>
Update: I might have over simplified my example. Here is a closer to reality example.
A company owns hotels. Hotels have Rooms. Management software delivers to the company daily Hotel_Statistics via an API. For lack of a better word, these Hotel_Statistics contain the hotel_id, daily check-ins, daily check-outs. In the company's back-office Rails app that I am working on, on the page displayed there is a table of hotels with their given most recent statistics. One line would look like:
Hotel Id: 123
Daily check-ins: 50
Daily check-outs: 48
Hotel Id: 124
Daily check-ins: 35
Daily check-outs: 37
The company wants to also display the running sum of the last 30 days of check-ins (outs, net check-ins).
To accomplish this, in my controller, I find the Hotel_Statics for the most recent date (normally yesterday).
latest_stat = HotelStatistic.order('date DESC, hotel_id DESC').first
#latest_date = latest_stat.date
#recent_stats = HotelStatistic.where(date: #latest_date).order('hotel.id ASC').all
I display the details of #recent_stats in my view.
Now, I would like to display in my view the sum of the last 30 days of #recent_stats.check_ins for each Hotel. My idea was to sum up the the last 30 days of check_ins statistics for a given Hotel like:
#recent_stats.each do |stat|
#last_30_days_check_ins = HotelStatistic.where(hotel_id: stat.hotel_id).where("date >= ?", Date.today - 30).sum(:check_ins)
end
The math works, but I need a way to access the 30 day sum variable for each hotel. I was a hoping to make this easy in the view by adding the hotel 30 day sum to the #recent_stats instance variable so in my view I could do:
<% #recent_stats.each do |statistic| %>
Hotel Id: <%= statistic.hotel_id %>
Daily check-ins: <%= statistic.check_ins %>
Last 30 days check-ins: <%= statistic.last_30_days_check_ins %>
<% end %>
Does this more realistic example change anything in your suggested answers? Thanks
The type of #foo_users is ActiveRecord::Relation. Trying to add age_sum as a new attribute to an ActiveRecord::Relation object doesn't make sense because semantically age_sum is not an attribute of ActiveRecord::Relation objects. It's better to store the sum of ages in a new instance variable, for example #user_age_sum.
UPDATE
Try the following
class HotelStatistic < ActiveRecord::Base
belongs_to :hotel
end
class Hotel < ActiveRecord::Base
has_many :hotel_statistics
def last_30_days_check_ins
self.hotel_statistics.where("date >= ?", 30.days.ago).sum(:check_ins)
end
end
Keep the existing code for building #recent_stats in the controller
In the view
<% #recent_stats.each do |statistic| %>
Hotel Id: <%= statistic.hotel_id %>
Daily check-ins: <%= statistic.check_ins %>
Last 30 days check-ins: <%= statistic.hotel.last_30_days_check_ins %>
<% end %>
Using select should solve your problem:
#users = User.select("*, SUM(age) as age_sum").where(name: 'John')
Now each User in the #users array will have a age_sum property. This is not 100% ideal as the value of the property will be the same on each instance, but it will work with how you've setup your view.
Edit
It's possible to dynamically define a method on an instance manually:
#foo_users.each do |foo|
def foo.age_sum; Users.where(name: 'John').sum(:age); end;
end
However while this is possible, it would have to be a very good use case to justify the negative impact this may have (such as on how readable, efficient and maintainable the code is). There are probably much better OO ways to solve the same problem

How do I remove days from date range?

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!

Validate date/time in another country, prevent delay in timezones

How do I validate if the date of an object is going on today, preventing delay timezones.
My Ruby's app hosted in the USA and my time zone is in another country.
Ex:
List of games to be played today.
<% #matches.each do |m| %>
<% if(m.date.today?) %>
<p>This match will be played today</p>
<% end %>
<% end %>
The 'if' sentence brings back the results of the matches to be played today, including upcoming games seven hours, server delay product.
Convert the date to the user's timezone.
m.date.in_time_zone(<user's time zone>).today?

Resources