Przyjazne linki, a polskie znaki

Witam!
Chciałem zaimplementować przyjazne adresy w swojej aplikacji, ale mam problem z polskimi znakami. Wszystko działa dopóki nie ma tam polskich znaków np. /region/Inowrocław. Informacje do bazy danych były ładowane przez migracje, to chyba dobry sposób? Domyślam się, że problem leży po stronie kodowania w bazie danych. Jakie kodowanie powinno być (w tym momencie jest latin1_swedish_ci)? Zmienić na utf8_bin czy utf8_polish_ci?
Mam tez więcej wątpliwości co do wpisywania polskich znaków w pasku adresu? Czy takie coś będzie działać tak samo jeśli użytkownik ma w systemie ustawione locale utf czy iso czy cp1250? Albo jak będą interpretowane spacje np. /region/nowy sącz ?
Mam też pytania dotyczące migracji. Czy kodowanie tych danych pompowanych do bazy zależy od kodowania systemowego i tego w jakim jest zapisany plik? Czy za pomocą migracji można zmienić kodowanie znaków w bazie danych?
Przepraszam za tak wiele pytań na raz, ale jedną z zalet Rails są właśnie te przyjazne linki.

Moim zdaniem nie powinieneś umieszczać danych (np. nazw miast) w URL-u. Powinien tam być ID. Czyli powinno być miasta/123, zamiast miasta/inowroclaw. Opinie pod tym względem są podzielone - gdzie indziej spotkasz zalecenia, żeby umieszczać w URL-u słowa kluczowe (niby SEO), ale ja ich nie podzielam.

Natomiast na pewno nie powinieneś umieszczać w URL-u polskich liter i spacji!

O kodowaniu polskich znaków w bazie danych, w Rails, i w przeglądarce możesz poczytać tutaj.

Rozumiane inaczej niż chcesz to zrobić: Rails nie zachęca do umieszczania danych w URL-u. Zachęca do URL-i z liczbowymi identyfikatorami.

Sadze, ze mozna tutaj znalezc zloty srodek (miedzy tym jak przyjazne adresy chce wykonac seban a tym, co na temat tego napisal qertoip).

Rozwiazaniem tego problemu jest zdefiniowanie w modelu metody to_param w nastepujacy sposob:

def to_param
  "#{id}-#{name.downcase.gsub(/[^[:alnum:]]/,'-')}".gsub(/-{2,}/,'-')
end

Oczywiscie, “name” nalezy zastapic nazwa pola, ktore ma byc umieszczone w parametrze. Dzieki temu otrzymujemy dla obiektu regionu “Nowy Sącz” o id=123 parametr: 123-nowy-sacz.

Numer id na poczatku pozwala nam w latwy sposob wyszukiwac obiekty na podstawie tego parametru. Wynika to z dzialania metody to_i klasy String:

irb> '123-nowy-sacz'.to_i
=> 123

Tak wiec mozna bez zadnych problemow stosowac w kontrolerach:

@region = Region.find(params[:region_id])

Pozdr.

Nie chcę zakładać nowego tematu a pytanie w miarę zogdne z tym tematem.
Budując stronkę napotkałem na taki problem: mam modele (np User itp itd), w nich mam zdefiniowane metody to_param, żeby generować sobie ładne URLe:

def to_param "#{id}-#{login}" end
Ale chciałbym jeszcze każdy z tych linków przepuścić przez metod, która obetnie mi kropki, ukośniki, spacje i takie tam nieprzyjazne rzeczy w adresie. Metoda ta jest taka sama dla każdego modelu, pytanie brzmi :wink:
Jak zdefiniować jedną metodę, żeby była dostępna dla wszystkich modeli?

[quote=msq]żeby generować sobie ładne URLe:

def to_param "#{id}-#{login}" end
[/quote]
To nie są ładne URL-e. Idziecie w złym kierunku z tym “kompromisem” id-dane. Jeśli znajdę czas, poświęcę temu artykuł na blogu (nie obiecuję).

Jak to w programowaniu obiektowym: zdefiniuj dla nich wspólną klasę bazową (dziedziczącą oczywiście z ActiveRecord::Base) i tam umieść metodę.

Heh, tak sądziłem, no cóż :slight_smile: Dzięki!

quertoip: napisz, napisz :slight_smile:

Bez sesnsu uzywac dziedziczenia w tym przypadku. Wystarczy dodac poprostu nowa metode do ActiveRecord::Base.

To kwestia gustu. Wolę traktować modyfikację środowiska jako ostateczność. W tym przypadku da się komfortowo wpiąć bez dotykania Rails. Ten sposób wydaje mi się bardziej estetyczny. Oba rozwiązania zajmują tyle samo kodu.

Dlaczego nie napisać tej metody w ApplicatioController ?

@qertoip
Nurtuje mnie ten post, że to nie są ładne URLe :wink:
Piszesz, że rails zachęca do URLi z danymi liczbowymi. Wiadomo, lepsze users/1
niż users?id=1
czy users?name=Ania
(ostatnie, to oczywiście rozwiązanie ZŁE ;))
ale z drugiej strony, urle mają być przyjemne do zapamiętania. To, że w przeglądarce mam zapamiętany adres domena.pl/users/1 to mi nic nie mówi, równie dobrze mógłbym mieć zapamiętany ten trudniejszy URL bo przecież i tak nie wyznam się, czy to dotyczyło użytkownika “Marek” czy “Ania” - a to jest wg mnie najważniejsze w “ładnych URLach”, taka była chyba idea ich tworzenia od zarania :wink:

miasta/123-nowy-sacz

To rozwiązanie-pułapka, łączące wady obu poprzedników.

Po pierwsze, adres jest nieprzyjazny: połączenie ID i nazwy gwarantuje, że nikt tego nie zapamięta ani nie wpisze z palca. Oczywiście miasta/123 też nie jest pod tym względem idealny, ale na pewno lepszy.

Po drugie, identyfikator zawiera rzeczywiste dane. Dane zawsze wcześniej czy później się zmieniają. W szczególności, zmieniają się nazwy miast… Podstawową cechą dobrego identyfikatora jest niezmienność w czasie.

Wreszcie po trzecie, wymaga pewnej gimnastyki by obsłużyć go w Rails. Nie zgłębiałem tego tematu. Potencjalnie może to komplikować i tak skomplikowany routing, zwłaszcza przy REST.

Mówisz, że “opisowy”. Identyfikator nie ma być opisowy. Od tego jest tytuł, wyświetlany zarówno w zakładkach, jak i w pasku adresu przy podpowiadaniu.

Jedyny realny plus tego rozwiązania to SEO… ale też tylko połowicznie, bo każda fraza zawierająca polskie literki jest spalona (Google nie mapuje polskich na łacińskie).

To właśnie ostre SEO doprowadziło do zboczonego pomysłu umieszczania tytułów artykułów w identyfikatorach. Teraz to ma coraz mniejsze znaczenie. Czy warto zawracać sobie głowę?

[quote=qertoip]miasta/123-nowy-sacz

To rozwiązanie-pułapka, łączące wady obu poprzedników.

Po pierwsze, adres jest nieprzyjazny: połączenie ID i nazwy gwarantuje, że nikt tego nie zapamięta ani nie wpisze z palca. Oczywiście miasta/123 też nie jest pod tym względem idealny, ale na pewno lepszy.[/quote]
Nie mówię, że ktokolwiek miałby pamiętać te id. Patrząc po sobie: włączam przeglądarkę, wpisuję w okienku dwie pierwsze literki domeny, a potem już tylko widzę, że odwiedziłem profil np user/1-Ania więc z łatwością go wybieram i odwiedzam ponownie. Rzadko używam historii w przeglądarce (jako osobnego panelu) bo wiem, że tak jak to opisuję szybciej znajdę stronkę, niż grzebiąc po historii.

Tu rzeczywiście może być trochę problem, aczkolwiek nie sądzę żeby takie URLe zmieniały się bardzo często. Biorąc za przykład chociażby wpisy w blogu czy uzytkowników: nie widzę sytuacji w której wpis w blogu możnaby zmienić na jakiś zupełnie inny, tak samo mając użytkowników z reguły nie zastępuję się jakiegoś użytkownika innym.

Obsłużenie linków id-login? Jeśli o to chodzi, to żadnej. Możesz przekazać params[:id] do Finda i on automatycznie wyciąga z niego liczbę, która jest na początku. Czyli Model.find(143) działa tak samo jak Model.find(143-A-tutaj-mamy-ladny-wpis). Nie trzeba więc przepisywać wszystkich linków, wystarczy tylko zmienić metodę to_param.
Tworzenie tych linków: zdefiniowanie jednej metody dla jednego modelu (która prawie tak samo wygląda w każdym przypadku)

No tutaj ja mam po prostu swoje zdanie :slight_smile: Jak wyżej wspomniałem, wolę szukać tego w adresie, a nie w historii czy strony (bo ten , może być za długi!)

I dlatego własnie moje pytanie na górze między innymi. W każdej fcji to_param możesz sobie modyfikować ten tytuł, zastępując chociażby polskie znaki diakretyczne na ich nie-diakretyczne odpowiedniki.