listing data dependant on associated database - ruby-on-rails

Wasn't sure how to title this question but here it goes.
I have two tables, Hotdesks and Bookings. Users can book a hotdesk.
In my controller I have an array #eastdesks containing all desks with a location of "East".
What I would like to do is to check which of these desks have been booked and display a list of available desks. This is my controller:
#eastdesk = Hotdesk.order("code ASC").where(:location => "East")
#booking = Booking.all
And this is my code so far:
<% #eastdesk.each do |ed| %>
<% #booking.each do |b| %>
<% if b.date == Date.today && b.type == "Hot Desk" %>
<% if b.desk == ed.code %>
<%= ed.code %> (Booked)
<% end %>
<% end %>
<% end %>
<% end %>
This ONLY shows those that have been booked.
I appreciate it is very ugly because I have been playing around. It is quite confusing but the t tables are associated vie the 'desk' column in bookings and the 'code' column in eastdesk. (i.e. booking with desk 553 will link to the desk with code 553) Hope that makes sense. Thanks for the help
EDIT ----
At the moment there are 2 desks in #eastdesk array (E90 and E23). The E90 desk has been booked for today and the E23 desk has not been booked at all. For the code above I am getting the following output:
E90 (Booked)
What I want to show is the desks that have NOT been booked. My Hotdesk model consists of:
has_many :bookings
I was thinking of adding the following to my bookings model but I am not sure as there ar different types of bookings and not all of them belong to a hot desk.
belongs_to :hotdesks

You can create an array holding 'Desk Codes' from booking table and use 'include?' method to check if this array contains the 'desk' value of #eastdeck.
Possible Solution:
#booking.map { |b| #booking_codes.push b.desk } // Creating a temporary array holding 'desk' from #booking
View:
<% #eastdesk.each do |ed| %>
<% #booking.each do |b| %>
<% if b.date == Date.today && b.type == "Hot Desk" && #booking_codes.include? b.desk %>
<%= ed.code %> (Booked)
<% end %>
<% end %>
<% end %>
PS: This may not be the nicest solution, but it may help :)

Related

Rails - Unique Array in View

Having a Bit of trouble displaying unique results from my database. I have a database called "Activities". Each Activity has an associated Sport through sport_id. There may be many activities with the same sport_id.
I want to display a list of all sports linked to the activities database without displaying (for example "Football") twice.
FYI : Venues have many Facilities and Facilities have many Activities.
Controller:
#sports = Sport.all
#activities = Activity.paginate(page: params[:page])
#facilities = Facility.where(venue_id: #venue.id)
View:
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").each do |a| %>
<li><%= Sport.find(a.sport_id).name %>, (<%= a.facility_id %>)</li>
<% end %>
<% end %>
This shows:
Football, (2)
Hockey, (2)
Hockey, (2)
Football, (5)
I would like to display just:
Football
Hockey
Any ideas?
A simple solution would be to reduce your array with ruby in the view using: uniq!
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").uniq! { |a| a.sport_id }.each do |a| %>
<li><%= link_to Sport.find(a.sport_id).name, Sport.find(a.sport_id) %></li>
<% end %>
<% end %>
Another way may be to perform a single query on your DB since Sport what you want to narrow down
In controller:
#sports = Sport.joins(activities: [facility: :venue]).where(facilities: { venue_id: #venue.id }).distinct
In view:
<% #sports.each do |sport| %>
<li><%= link_to sport.name, sport %></li>
<% end %>
I am not sure about your DB schema so I went with what I thought you would have done, but it might needs some tweakings.
I hope I helped you.
try to use reject before each
<% #facilities.reject{your condition here}.each do |f| %>

how to check whether association exists rails

I have two tables
Post
Category
I have the following code in my controller:
#category = Category.find(id)
Suppose consider category as mobile, car, bike
I need to check the existence of mobile or car or bike. So that I can disable the input element. I tried:
<% #category.each do |cat| %>
<% if cat.posts.exists %>
class = 'active'
<% else %>
class = 'inactive'
<% end %>
<div class="#{class}"><%= cat.name %></div>
<% end %>
The above code always runs the else condition.
Following are the categories:
Mobile
Car
Bike
If in my post table with column category_id has the field with value 1 then mobile should have a class active and the other two should be inactive.
I think you are looking for the any? method:
<% #category.each do |cat| %>
<div class="#{cat.posts.any? ? 'active' : 'inactive'}"><%= cat.name %></div>
<% end %>

grouping children by parent attribute

Here's what I am trying to achieve:
Group_x.name
member1.name -- member1.join_date -- etc
member2.name -- member2.join_date -- etc
...
Group_y.name
member1.name -- member1.join_date -- etc
member2.name -- member2.join_date -- etc
...
What I'm going for is really very similar to this although the implementation there doesn't work for me.
I've gotten this far in my controller:
def index
# https://stackoverflow.com/a/17835000/2128691
#user_group_ids = current_user.student_groups.map(&:id)
#students = Student.where('student_group_id IN (?)', #user_group_ids)
# https://stackoverflow.com/a/10083791/2128691
#students_by_group = #students.uniq {|s| s.student_group_id}
#title = "All students"
end
and calling the following in my view -
<% #students_by_group.all.each do |x| %>
<p>
<%= "#{x}" %>
</p>
<% end %>
gives me a list of all student objects. if i call <%= "#{x.name}" %> or <%= "#{x.created_at}" %>, etc, I get the correct information, and everything is great.
But now that I have all this information, how can I put the group.name (in my code it would be x.student_group.name) as a header for all of the students for which that group_name is true?
I think you need to use group_by on #students_by_group like this:
#students_by_group = #students_by_group.group_by { |s| s.student_group }
This would return a hash with the keys being the student group objects and the values being the students that belongs to this group, then you can do this in your view:
<% #students_by_group.each do |group, students| %>
<h3><%= group.name %></h3>
<% students.each do |x| %>
<p>
<%= "#{x}" %>
</p>
<% end %>
<% end %>
As an additional note, the group_by would fire a query for each student, so you may want to eagerly load the student group for each student like this for some performance gain:
#students = Student.where('student_group_id IN (?)', #user_group_ids).includes(:student_group)

Rails. Check if ANY of the attributes in a collection is blank

I have a collection of invoices. One of the attributes is exchange_rate (is used to calculate the currency from US dollars for Mexican pesos). I need to create a warning if even ONE of the records doesn't have an exchange_rate set.
I could check if the exchange_rate of a record in a collection is blank like this...
<% is_blank = false %>
<% #invoices.each do |invoice| %>
<% if invoice.exchange_rate.blank? %>
<% is_blank = true %>
<% end %>
<% end %>
<% if is_blank %>
shoot warning: all of the invoices must have an exchange rate in order
to calculate pesos total
<% end %>
What is a more Railsy way of writing the above?
Simply like this, using the Enumerable#any? method:
<% if #invoices.any? { |i| i.exchange_rate.blank? } %>
shoot warning: all of the invoices must have an exchange rate in order
to calculate pesos total
<% end %>

Refactoring code out of the view

I have the following view code which displays events, along with headers informing the user if the following events occured today, yesterday, or in the past week.
It all works fine, but I would prefer to refactor it out of the view, I can't put it in a helper because it needs to maintain the variables state between loop iterations. Any idea how to tidy this up? thanks
<% displayed_week_already = false %>
<% displayed_yesterday_already = false %>
<% displayed_today_already = false %>
<% #events.each do |event| %>
<%= event.title &>
<% if (Time.now - 1.week) > event.created_at && !displayed_week_already %>
<% displayed_week_already = true %>
Events in past week
<% elsif (Time.now - 1.day) > event.created_at && (Time.now - 2.day) < event.created_at && !displayed_yesterday_already %>
<% displayed_yesterday_already = true %>
Events yesterday
<% elsif (Time.now - 1.day) < event.created_at && !displayed_today_already %>
<% displayed_today_already = true %>
Events in past day
<% end %>
<% end %>
Expected output would be:
Events in past day
John created a new artice
Dan commented on article 1
Sue deleted article 2
Events yesterday
Sue created a new article
Events in past week
Carol was promoted
Dan cerated a new article
I might do something like the following. I am leaving out the implemented methods defined on the model itself.
existing view
<%= render "events", :title => "Events in past day", :events => from_today(#events) %>
<%= render "events", :title => "Events yesterday", :events => from_yesterday(#events) %>
<%= render "events", :title => "Events in past week", :events => from_this_week(#events) %>
_events.html.erb
<% if events.present? %>
<%= title %>
<% events.each do |event| %>
<%= event.title %>
<% end %>
<% end %>
app/helpers/event_display_helper.rb
module EventDisplayHelper
def from_today(events)
events.select{|x| x.happened_today?}
end
def from_yesterday(events)
events.select{|x| x.happened_yesterday?}
end
def from_this_week(events)
events.select{|x| x.happened_this_week_before_yesterday?}
end
end
You could easily do this in the model, with named scopes (I'm assuming Rails 3 because that's what I know best). You'll need to define them yourself but they're pretty simple.
#last_week = #event.last_week
#yesterday = #event.yesterday
#today = #event.today
Then just iterate over each of the groups in your view. Should make it a lot cleaner and you won't need so much logic, as it's where it actually belongs.

Resources