我是 Rails 的新手,正在做面试的测试。
几乎达到了预期的结果,您可以在下面找到代码。
数据示例:
Bookings
id,room_id,start_date,end_date,number_of_guests
1,1,2015-06-01,2015-06-07,1
2,3,2015-06-01,2015-06-07,2
3,5,2015-06-01,2015-06-07,2
2001,6,2015-06-01,2015-06-07,2
...
Hosts
id,name,address
1,Mr Host 1,1 Camden
2,Mr Host 2,2 Camden Street
3,Mr Host 3,3 Camden Street
4,Mr Host 4,4 Camden Street
...
Rooms
id,host_id,capacity
1,1,2
2,1,2
3,2,2
4,2,2
...
事件记录:
class Room < ActiveRecord::Base
belongs_to :host
has_many :bookings
end
class Host < ActiveRecord::Base
has_many :rooms
end
class Booking < ActiveRecord::Base
belongs_to :room
end
Controller :
start_date = '2015-06-01' # hardcoded value for testing purposes
end_date = '2015-06-07' # hardcoded value for testing purposes
@available_rooms = Room.select(:host_id, :name, :address, :id, :number_of_guests ,:capacity)
.joins(:bookings, :host)
.where("bookings.number_of_guests <> rooms.capacity
AND ? < rooms.capacity
AND ? <= bookings.start_date
AND ? <= bookings.end_date", params[:guests], start_date, end_date)
@booked_rooms = Room.select(:host_id, :name, :address, :id, :number_of_guests, :capacity)
.joins(:bookings, :host)
@total_rooms = Room.select(:host_id, :name, :address, :id, "0 as number_of_guests", :capacity)
.joins(:host)
@rooms = ((@total_rooms - @booked_rooms) + @available_rooms).sort_by(&:id)
看法:
<% if @rooms %>
<section class="rooms">
<ul class="list-unstyled list-rooms">
<% for room in @rooms %>
<li class="clearfix">
<article>
<div class="description">
<header>
<h2>host#<%= "#{room.host_id}: #{room.name}" %></h2>
<h3><%= "#{room.address} "%></h3>
</header>
<p>room#<%= "#{room.id} is available (#{room.number_of_guests} booked, #{room.capacity - room.number_of_guests} free out of total #{room.capacity})" %></p>
</div>
</article>
</li>
<% end %>
</ul>
</section>
<% end %>
当前结果:
host#1: Mr Host 1
1 Camden Street
room#1 is available (1 booked, 1 free out of 2 total)
host#1: Mr Host 1
1 Camden Street
room#2 is available (0 booked, 2 free out of 2 total)
host#2: Mr Host 2
2 Camden Street
room#4 is available (0 booked, 2 free out of 2 total)
host#4: Mr Host 4
4 Camden Street
room#8 is available (0 booked, 2 free out of 2 total)
host#5: Mr Host 5
5 Camden Street
room#9 is available (1 booked, 1 free out of 2 total)
host#5: Mr Host 5
5 Camden Street
room#10 is available (0 booked, 2 free out of 2 total)
预期结果:
host#1: Mr Host 1
1 Camden Street
room#1 is available (1 booked, 1 free out of 2 total)
room#2 is available (0 booked, 2 free out of 2 total)
host#2: Mr Host 2
2 Camden Street
room#4 is available (0 booked, 2 free out of 2 total)
host#4: Mr Host 4
4 Camden Street
room#8 is available (0 booked, 2 free out of 2 total)
host#5: Mr Host 5
5 Camden Street
room#9 is available (1 booked, 1 free out of 2 total)
room#10 is available (0 booked, 2 free out of 2 total)
我正在考虑使用 jquery 来获得预期的结果,但我必须有一种方法可以通过事件记录或在 View 中调用某种帮助程序来实现这一点。提前致谢。
理想情况下,我想重写查询以检索如下行的结果:
host_id, address, total_rooms, room_id[0], booked[0], capacity[0], ... , room_id[n], booked[n], capacity[n]
因此,对于前两行,我们将有:
1, 1 Camden Street, 2, 1, 1, 2, 2, 0, 2
2, 2 Camden Street, 1, 4, 0, 2
相当于前端的结果:
主持人#1:主持人1先生
1 卡姆登街
房间#1 可用(预订了 1 个,总共 2 个中有 1 个免费)
房间#2 可用(0 个预订,2 个免费,共 2 个)
主持人#2:主持人先生2
2 卡姆登街
房间#4 可用(0 个预订,2 个免费,共 2 个)
最佳答案
您不能在 SQL 级别执行此操作。 SQL 返回统一的行,您可以按照自己的喜好对它们进行排序,但在 SQL 中对行进行分组不能这样工作。您不能使用它来返回一对多关系的部分行;它将为每一行返回完整的连接记录。
如果您只想输出顶级记录(在本例中为“主机”),然后多次输出关联记录(“房间”),则需要在前端对结果进行分组:
#...
@rooms = ((@total_rooms - @booked_rooms) + @available_rooms).sort_by(&:id)
# Produce a mapping of hosts to their rooms
@rooms_by_host = @rooms.group_by do |room|
{ id: host_id, address: room.address, name: room.name }
end
group_by
将对块返回相同值的元素进行分组。在这种情况下,任何具有相同 host_id
的房间, address
和 name
将在返回的散列中组合成一个嵌套数组。在您看来,您现在将有两个循环:一个循环遍历主机 => 房间映射的外部循环,以及循环遍历其房间的每个主机的内部循环:
<section class="rooms">
<ul class="list-unstyled list-rooms">
<% @rooms_by_host.each do |host, rooms| %>
<li class="clearfix">
<article>
<div class="description">
<header>
<h2>host#<%= host[:id] %> - <%= host[:name] %></h2>
<h3><%= host[:address] %></h3>
</header>
<ul class="rooms">
<% rooms.each do |room %>
<li>room#<%= room.id %> is available (<%= room.number_of_guests %> booked, <%= room.capacity - room.number_of_guests %> free out of total <%= room.capacity %>)</li>
<% end %>
</ul>
</div>
</article>
</li>
<% end %>
</ul>
</section>
如果您担心在面试中如何展示自己,您应该考虑以下几点:
for x in y
在 ruby 。惯用的循环方式是 y.each do |x|
.使用 for x in y
尖叫缺乏经验。 <% if @rooms %>
是无用的支票,@rooms
是一个数组,它永远不能是一个假值。您需要 if @rooms.present?
或 if @rooms.any?
<%= %>
和 "#{...}"
.内部#{}
是完全多余的。你做过的每个地方...<%= "#{room.address} "%>
你应该这样做
<%= room.address %>
.where("bookings.number_of_guests <> rooms.capacity
AND ? < rooms.capacity
AND ? <= bookings.start_date
AND ? <= bookings.end_date", params[:guests], start_date, end_date)
用这个
.where('bookings.number_of_guests <> rooms.capacity')
.where('? < rooms.capactiy', params[:guests])
.where('? <= bookings.start_date', start_date)
.where('? <= bookings.end_date', end_date)
它还使您的参数更接近它们的使用位置。
<ul class="rooms">
<%= render rooms %>
</ul>
然后将循环体移动到
app/views/rooms/_room.html.erb
<li>room#<%= room.id %> is available (<%= room.number_of_guests %> booked, <%= room.capacity - room.number_of_guests %> free out of total <%= room.capacity %>)</li>
关于ruby-on-rails - Activerecord rails 合并多个选择结果并在 View 中呈现行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29445255/