2016-04-03 4 views
0

У меня есть таблица, которая отображает несколько разных атрибутов данных, я следил за railscast # 228, чтобы сортировать столбцы. Почти все работает, за исключением одного заголовка с именем «groups», когда я нажимаю на эту ссылку, меняю стрелку направления, и она возвращается обратно к исходному заголовку (я сделаю снимок экрана для ясности). У меня есть помощник, контроллер и представление, которое выполняет функцию кода проблемы, теперь я покажу вам соответствующий код и сделаю все возможное, чтобы описать все, что вам нужно знать, чтобы помочь мне. Вот мое мнение. Вы можете увидеть в блоке @people, что проблема <td><%= person.groups.order(:id).pluck(:name).to_sentence %></td>.Glyphicon Arrow help для сортировки столбцов

<table class="table table-striped"> 
<thead> 
    <tr> 
    <th><%= sortable 'phone_number', 'Phone Number'%></th> 
    <th><%= sortable 'subscribed', 'Subscribed'%></th> 
    <th><%= sortable 'city' %></th> 
    <th><%= sortable 'state' %></th> 
    <th><%= sortable 'zip' %></th> 
    <th><%= sortable 'country' %></th> 
    <th><%= sortable 'groups' %></th> 
    <th><%= sortable 'created_at', "Joined" %></th> 
    </tr> 
    </thead> 

<% @people.each do |person| %> 
     <tr> 
     <td><%= person.phone_number %></td> 
     <td><%= person.subscribed? ? "Yes" : "No" %></td> 
     <td><%= person.city %></td> 
     <td><%= person.state %></td> 
     <td><%= person.zip %></td> 
     <td><%= person.country %></td> 
     <td><%= person.groups.order(:id).pluck(:name).to_sentence %></td> 
     <td><%= time_ago_in_words person.created_at %> ago</td> 
     </tr> 
     <% end %> 

Вот сортировкой вспомогательный метод

def sortable(column, title = nil) 
title ||= column.titleize 
if column != sort_column 
    css_class = nil 
    direction = "asc" 
elsif sort_direction == "asc" 
    css_class = "glyphicon glyphicon-triangle-top" 
    direction = "desc" 
else 
    css_class = "glyphicon glyphicon-triangle-bottom" 
    direction = "asc" 
end 
link_to "#{title} <span class='#{css_class}'></span>".html_safe, sort: column, direction: direction 
end 

вот мой контроллер

def index 
@people = Person.order(sort_column => sort_direction) 
@groups = Group.all 
end 

Это методы сортировки в частном

def sort_column 
    Person.column_names.include?(params[:sort]) ? params[:sort] : "phone_number" 
    end 

    def sort_direction 
%w(asc desc).include?(params[:direction]) ? params[:direction] : "asc" 
    end 

вот скриншот, это результат щелкните заголовок «Группы». как вы можете видеть, он возвращается к номеру телефона. * note - Каждый другой заголовок сортирует и отображает стрелку сортировки правильно.

enter image description here

ответ

2

Основная причина вашей проблемы не в коде вы указали в своем вопросе, но в примерах кода в скринкаст. Существует такой метод, и я предполагаю, что вы реализовали подобный метод:

def sort_column 
    Product.column_names.include?(params[:sort]) ? params[:sort] : "name" 
end 

Заметьте, что groups в таблице не имя столбца базы данных, но имя ассоциации к другой модели. Поэтому этот метод всегда будет возвращать "name" (или я принимаю "phone_number" в вашем методе).

Вы не можете упорядочивать ассоциации в активной записи так же, как столбцы. Могут быть способы обходного пути, но это зависит от вашего определения того, что сортировать по groups ассоциация означает: вы хотите отсортировать записи в столбце Группы по именам групп, количеству групп или идентификаторам группы?


Если вы хотите реализовать сортировку по ассоциациям, то вам нужно сделать две вещи. Прежде всего позвольте метод sort_column принять имя ассоциации в дополнение к именам столбцов:

def sort_column 
    sortables = Person.column_names + ['groups'] 
    sortables.include?(params[:sort]) ? params[:sort] : 'phone_number' 
end 

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

# in the model: 
scope :sort_by, lambda { |options| 
    if options.key == ['groups'] 
    scope = select('DISTINCT people.*').joins(:groups) 
    if options.values == ['asc'] 
     scope.order('MIN(groups.name)') 
    else 
     scope.order('MAX(groups.name)') 
    end 
    else 
    order(options) 
    end 
} 

# in the controller 
@people = Person.sort_by(sort_column => sort_direction) 

Отказ от ответственности: Я не уверен, действительно ли область действия работает так, как вы ожидаете, что сортировка будет работать. Возможно, это сразу вызовет ошибку. достаточно просто написать такой код без возможности фактически запустить его против базы данных. Но вы получаете идею: когда вы хотите сортировать по ассоциации вместо столбца, это становится беспорядочным, потому что это не имеет никакого отношения к скринкасту, на который вы смотрели ...

+0

Да, я хочу сортировать по именам групп – Bitwise

+0

@ CameronBass Как сортировать по именам групп, когда в этом столбце есть несколько групп?Если есть столбец с 'visitor', один с' guest, staff' и one with 'volunteer, dance' - какой ваш предпочтительный порядок и почему? – spickermann

+0

Я думал просто в алфавитном порядке, как если бы был человек в просто «штат» и человек в «добровольце», пользователь мог просто сортировать этот путь. По общему признанию, это было бы не очень полезно, но это обеспечило бы непрерывность на всей странице. – Bitwise

Смежные вопросы