Jak podzielić długą listę alfabetycznie?

Dzień Dobry,

To moja pierwsza praca w RoR, mająca jakiekolwiek praktyczne zastosowanie, zatem proszę o cierpliwość. Chcę podzielić długą listę linków-nazwisk na listy nazwisk zaczynających się od kolejnych liter alfabetu i dodać stronę z linkami do każdej z tych list. Dobrze by było gdyby ta strona nie była tylko ciągiem linków-liter ale zawierała linki złożone z pierwszego i ostatniego nazwisko na daną literę, tzn.:

Ajdukiewicz-Axentowicz
Bacciarelli-Bullmeyer
Carowscha-Czyżewski

Żaboklicki-Żytkiewicz

W bazie są dwie tabele works i authors.

works:

±-----------±---------------------±-----±----±--------------------±---------------+
| Field | Type | Null | Key | Default | Extra |
±-----------±---------------------±-----±----±--------------------±---------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment|
| author_id | mediumint(8) | YES | | NULL |
| tytul | varchar(100) | NO | | | |
| created_on | timestamp | NO | | CURRENT_TIMESTAMP| |
| updated_on | timestamp | NO | | 0000-00-00 00:00:00 | |
±-----------±---------------------±-----±----±--------------------±---------------+

authors:

±-----------±----------------------±-----±----±--------------------±------+
| Field | Type | Null | Key | Default | Extra |
±-----------±----------------------±-----±----±--------------------±------+
| id | mediumint(8) unsigned | NO | PRI | | |
| name | varchar(60) | NO | | | |
| created_on | timestamp | NO | |CURRENT_TIMESTAMP| |
| updated_on | timestamp | NO | | 0000-00-00 00:00:00| |
±-----------±----------------------±-----±----±--------------------±------+

nazwisko jest w polu name.

Z góry dziękuję za wszelkie rady

Piotr

No dobrze, ale w którym miejscu jest problem?

Przykładowo, tak możesz pogrupować autorów według pierwszej litery nazwiska:

authors = Author.find( :all ).group_by { |author| author.name[0].chr }

authors będzie słownikiem: litera => [autor1, autor2, …]

Wyplucie tego na stronę jest proste.

Niestety jeszcze nie dla mnie :frowning: Jeżeli mój dodtychczasowy widok wyglądał tak jak poniżej, to co w nim należy zmienić, żeby w ogóle coś się wyświetliło? Przy okazji: dlaczego “authors” a nie “@authors”?

welcome.rhtml

Twórcy:

    <% @authors.each do |author| %>
  • <%= link_to "#{author.name}", :controller => "author", :action => "show", :id => author.id %>
  • <% end %>
#############################

Dzięki z góry.

P.

No to zdążyłem sam sobie odpowiedzieć i nauczyć się w międzyczasie jak wypuszczać zawartość hasha na stronę.

show_solution_1.rhtml

Twórcy:

<% @authors.each do |firstletter, authors| %>

<%= firstletter %>

<% for author in authors %>

<%= link_to "#{author.name}", :controller => "author", :action => "show", :id => author.id %>
<% end %> <% end %>

####################################

Wszystko gra i buczy, ale…

  1. Małe i duże litery są traktowane jako osobne grupy.

  2. Kolejność liter jest przypadkowa.

  3. W bazie mam dane w unikodzie, co nie było żadnym problemem do momentu (tak myślę) dopóki nie była używana funkcja chr która pewnie nie ma o tym bladego pojęcia, (a w perlu byłoby tak łatwo :frowning: i sortuje według pierwszego bajtu. Skutek jest zabawny np:


Ćwikliński Zefiryn
Ćmelik

a powinno być :

Ć
Ćwikliński Zefiryn
Ćmelik

Jedna sprawa to powyższe problemy a druga, to to, że taka lista nie za bardzo nadaje się do użytku w moim przypadku (ponad 4500 nazwisk i będzie więcej). Zatem pozostaje pytanie jak zrobić indeks z samymi literami (a raczej pierwszymi i ostatnimi nazwiskami na daną literę ) z którego wchodziłoby się na strony z nazwiskami zaczynającymi się na jedną literę (obawiam się że te strony też przydałoby się podzielić w niektórych przypadkach na mniejsze).

P.S.

authors nie chce mi działać. Musi być @authors .

http://api.rubyonrails.com/classes/ActionController/Pagination.html#M000130

http://api.rubyonrails.com/classes/ActionView/Helpers/PaginationHelper.html#M000504

To chyba najprostsza forma dzielenia kolekcji na strony. a to jak maja byc posortowane obiekty podajesz jak w metodzie find (:order)

A co z tym ??? Guide: Things You Shouldn’t Be Doing In Rails Tam grożą śmiercią lub kalectwem w przypadku używania “built-in pagination”. Wolę nie ryzykować. Poza tym podział na strony o określonej wielkości musi nastąpić dopiero po podziale na strony nazwisk na konkretną literę. :order w find nie zadziała bo potem jest group_by która to metoda zwraca hasha, a ten jak wiadomo ze swej natury nie jest nijak posortowany.

A to ciekawe - nie wiedziałem o tym, uzywalem paginate i nie polozyl serwera na kolana:) Musze zglebic ten temat w takim razie.

To mi się zaczyna podobać. Posortowałem wstawiając sort w pierwszą linijkę w widoku

show_solution_1.rhtml

Twórcy:

<% @authors.sort.each do |firstletter, authors| %>

<%= firstletter %>

<% for author in authors %>

<%= link_to "#{author.name}", :controller => "author", :action => "show", :id => author.id %>
<% end %> <% end %> ############################

I zadziałało. Do pewnego stopnia niestety. Nazwiska są pogrupowane na A,B,C itd. ale na końcu jest:


Überrück Wilhelm

Ćwikliński Zefiryn
Ćmelik

Łaszczyński Bolesław
Łukaszewicz Józafat Ignacy
Żmurko Franciszek
Świeykowski Aleksander
Żukowski Stanisław
Łoś Waldemar
[…]

Jak zmusić railsy żeby sortowały po polsku?

Ruby nie ma wciąż dobrej biblioteki Unicode (tak jak Python), więc w Ruby trzeba się męczyć. Ale zdecydowanie najlepiej zwalić sortowanie na bazę zamiast na Rubiego. A w bazie ustaw polskie collations to będzie trzymać się reguł jęz. polskiego. Wtedy wystarczy proste:

authors = Author.find :all, :sort => 'name'

Zobacz też artykuł “Polskie literki w Ruby on Rails

Natknąłem się na coś takiego, jednakże nie sprawdzałem. Można spróbować:
http://snippets.dzone.com/posts/show/2786

[quote=radarek]Natknąłem się na coś takiego, jednakże nie sprawdzałem. Można spróbować:
http://snippets.dzone.com/posts/show/2786[/quote]
To wszystko badziewie. Implementację UTF-8 w Railsach od 1.2 daje Multibyte, ale to też badziewie. UTF-8 to wciąż tylko ciąg bajtów, nie zawiera w sobie informacji o języku aby trzymać się jego reguł. Co mi z tego, że metoda size() rozpozna ilość znaków. A co z sortowaniem? Np. z tekstu kodowanego w UTF-8 nie wynika, czy mają być uwzględniane reguły języka polskiego, rosyjskiego, czeskiego czy japońskiego. A Python to potrafi, bo operuje na obiektach unikodowych które mogą przechowywać taką informację. I dzięki temu można tak samo traktować duże i małe znaki w operacjach na tekście (włącznie z wyrażeniami regularnymi). Dlatego, jeśli ktoś chce porządnie sortować teksty którze i tak trzyma w bazie, niech użyje do tego bazy z ustawionymi regułami językowymi (chodzi o opcję collations). Z Ruby trzeba poczekać do wersji 2.0 która dopiero wtedy będzie mieć zaimplementowany Unicode.