Может ли это быть преобразовано в один вызов базы данных? - PullRequest
0 голосов
/ 19 августа 2011

У меня есть список событий в модели Events.Что мне нужно сделать, так это визуально сгруппировать события по городам / штатам.

Визуально это будет выглядеть так:

Tracking details

Вот урезанный видчто я делаю, на мой взгляд, чтобы это произошло:

<% @number.events.locations.each do |location| %>
  <li>
    <h4><%= "#{location.city}, #{location.state}" %></h4>
    <ol>
    <% @number.events.city_state(location).each do |event| %>
      <li><%= event.status %></li>
    <% end %>
    </ol>
  </li>
<% end %>

И соответствующие области:

scope :locations, :group => 'city, state'
scope :city_state, lambda {|location| {:conditions => ["city = ? AND state = ?", location.city, location.state] }}

Проблема, однако, в том, что я делаю дополнительную базу данныхзвоните для каждого местоположения.

Так можно ли свести это к одному запросу?

Ответы [ 2 ]

1 голос
/ 19 августа 2011

Используйте готовую загрузку для предварительного извлечения ассоциаций из вашей базы данных:

Если вы извлекаете все свои события одновременно, вы можете изменить его, чтобы предварительно загрузить ассоциации местоположений для событий:

Event.all      # only loads Event objects from the database

#maybe try...

Event.includes(:locations)    # loads Event objects and their Locations

Если вам нужны события для какого-либо другого объекта (например, вашего @number объекта), вы можете захотеть сделать что-то подобное в вашем контроллере, например:

@number = Number.where(:id => whatever).includes(:events => :locations)

Теперь в этом примере ваш @number объект будет извлечен из базы данных вместе со всеми его событиями и местоположениями всех этих событий.

См. Руководство Rails для получения дополнительной информации об этом: http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

Обновлено с моим ответом из комментариев :

Вместо того, чтобы вообще использовать области, вы можете просто использовать Ruby, чтобы выполнить всю работу за вас, и исключить ActiveRecord и дополнительные вызовы базы данных из цикла.

Enumerable#group_by будет принимать коллекцию и группировать по указанному вами атрибуту. В этом случае вы можете взять все события, сгруппированные по городу и штату, а затем выполнить итерацию по возвращаемому хешу:

events = Event.all
events.group_by { |e| "#{e.city}, #{e.state}" }
# => {"Birmingham, AL" => [<event>, <event>, <event>], "Nashville, TN" => [<event>, <event>]}

Это может быть немного менее красиво, чем использование областей, но это позволяет вам сделать один вызов базы данных и оставить все как есть.

0 голосов
/ 20 августа 2011

Вот решение O (n ^ 2), предполагая, что ваш цикл locations.each do |location| работает так, как объявлено. Следует сократить до 2 дБ.

<% @number.events.locations.each do |location| %>
  <li>
    <h4><%= "#{location.city}, #{location.state}" -%></h4>
    <ol>
      <% @number.events.each do |event| %>
        <% if event.city == location.city and event.state == location.state %>
        <li><%= event.status -%></li>
        <% end %>
      <% end %>
    </ol>
  </li>
<% end %>

Еще не проверено, зайду позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...