2010-07-19 3 views
1

Я создаю список, который будет сортироваться по алфавиту, и я хочу найти решение для захвата результата базы данных и сортировки по алфавиту.Алфавитные списки с рубинами на рельсах

Любая помощь очень ценится!

+0

('A' .. 'Z'). Каждый из них является только началом этого ... Я имею в виду, вы не хотите делать запрос базы данных для каждой буквы, не так ли? – giraff

ответ

1

Хм, если у вас есть список, который не слишком массивным, вы можете просто сделать это наивно нравится:

(Это предполагает, что вы имеете модель Company, которая имеет атрибут name)

@grouped = {} 
Company.all.each do |company| 
    letter = company.name.slice(0,1).upcase 
    @grouped[letter] ||= [] 
    @grouped[letter] << company 
end 

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

<ul> 
    <% @grouped.keys.sort.each do |letter| -%> 
    <li> 
     <h2><%= letter %></h2> 
     <ul> 
     <% @grouped[letter].each do |company| -%> 
      <li><%= company.name %></li> 
     <% end -%> 
     </ul> 
    </li> 
    <% end -%> 
</ul> 

Update: Если вы хотите EXTEN d логика на том, что 'буква', вы, вероятно, переместить логику в модель, например:

class Company 
    # ... code 

    def initial 
    # find a number at the start of the string if it exists 
    m = self.name.match(/^\d+/) 
    return m[0] if m 
    # or return the first letter upcased otherwise 
    return self.name.slice(0, 1).upcase 
    end 
end 
+0

Спасибо! ;) Получил это, чтобы работать. Если первое «письмо» на самом деле является числом, как я могу просто вернуть «123»? –

+0

См. Мое обновление. С помощью нового метода вы можете просто изменить строку 'letter =' на 'letter = company.initial' – rfunduk

+0

Похоже, что' group_by' - интересный способ сделать это тоже. '@grouped = Company.all.group_by (&: initial)' <- это все еще принадлежит контроллеру IMO. – rfunduk

4

Опираясь на thenduks выше, мне нравится:

Company.rb

def initial 
    return '?' if name.blank? 
    # name.[0].upcase (updated to get the first character) 
    name.slice(1).chr.upcase 
end 

вид

<% # Company.all.group_by(&initial) do |initial, companies| (updated) %> 

<% Company.all.group_by(&:initial).each do |initial, companies| %> 
    <%= content_tag(:h2, initial)%> 
    <% companies.each do |company|%> 
    <%= link_to(company.name, company%> 
    <% end %> 
<% end %> 
+0

Вам нужно добавить структуру вокруг <% = link_to (company.name, company%>, но вы получите значение –

+0

Не могу заставить это работать. Я хотел использовать это, потому что он был «чище». Любые предложения? –

+0

Josh - если вам интересно, я отредактировал и протестировал его. Несколько мелких ошибок в моей предыдущей версии. –

0

Попробуйте это:

g = Company.all.group_by{|c|c.name.upcase[0..0]} 
('A'..'Z').each do |letter| 
    companies = g[letter] || [] 
    # process the name and the letter 
end 

Это будет работать даже в сценариях, если у вас нет элементов для нескольких букв.

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

+2

'('A' .. 'Z'). To_a.each do | letter |' is еще лучше – jwilsco

+0

'('A' .. 'Z'), каждый из которых выполняет | letter |' работает для меня на ruby ​​2.1. – cesoid

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