link_to, create_path - jak i gdzie?

Mam trochę inną adresację niż /controller/action, w związku z tym pytanie, jak (jakim mechanizmem) zrealizować budowanie adresów do moich zasobów na stronie?

Na kilku różnych odsłonach będzie jakaś lista elementów biżuterii, biżuteria zawsze pokazywana będzie na odsłonach /bizuteria/jakas-nazwa-bizuterii/id
Gdzie umieścić metodę do budowania takiego adresu dla elementów biżuterii? (składającą “/bizuteria/” i create_url(nazwa) i “/” i bizuteria.id w calosc), żeby potem porządnie z tego korzystać i nie sklejać tego za każdym razem?

Musisz sporo o railsowym routingu poczytać – masz Obiego “The Rails Way”? Tam to całkiem nieźle jest wyjaśnione.

Jeśli jakas-nazwa-bizuterii przekłada się zawsze na jakąś akcję lub kontroler (lub nawet id), to /bizuteria powinna być namespace’em ścieżek branych pod uwagę. To tak na wstępie. “rails namespaced routes”. Potem “rails named routes”. Potem powinno już być z górki :slight_smile:

Dzięki.

jakas-nazwa-bizuterii nie przekłada się na żadną akcje, ani kontroler, jest w adresie ze względów SEO, /controller/trash-trash-trash/id -> :controller => jewlery :action => view :id => id

Pytanie o miejsce umieszczenia metody do generowania lisnku do odsłony elementu biżuterii pozostaje aktualne…

@zmaliszewska:

Użyj named_route, np:

config/routes.rb

map.show_jewel '/bizuteria/:slug/:id', :controller => 'jewlery', :action => 'view'

Powinno być “jewellery” a nie “jewlery” tak BTW.

model Jewel (przykład), potrzebujesz metody slug która wygeneruje słowa kluczowe na potrzeby SEO:

[code=ruby]class Jewel < ActiveRecord::Base

def slug
self.name.gsub(/[^[:alnum:]]/,’-’) # zamien wszysktkie znaki z name ktore nie sa alfanumeryczna na -
end
end[/code]
generowanie linka, zakladajac, że @jewel to obiekt modelu AR.

<%= link_to @jewel.name, show_jewel_path(@jewel.slug, @jewel.id) -%>

Dziękuje pięknie! Dokładnie o to mi chodziło :slight_smile: A “model AR” to???

show_jewel_path - nazwa tej metody powstaje na podstawie definicji z routes.rb?

A co do mojego ‘jewlery’ to rzeczywiście była literówka, bo używam ‘jewelry’ a ‘jewellery’ jest brytyjskie - ale to już tematy na inne forum! Dzięki jeszcze raz, zabieram się za implementację.

AR = ActiveRecord - mówiąc prościej: jak coś wyciągasz z bazy, to jest to obiekt AR (poza kilkoma przypadkami, ale żeby nie mieszać w głowie, to pozostańmy, że zawsze jest to obiekt ar)

Dzięki, a jeszcze jedno pytanie do tego wątku:
Poprzednio działało mi (id było jakoś odczytywane z ?id=):

map.connect "bizuteria/:name.html", :controller => 'jewelry', :action => 'show'

A teraz z html nie działa:

map.show_jewelry "bizuteria/:slug.html?id=:id", :controller => 'jewelry', :action => 'show'

Komunikatu błędu: undefined method `has_key?’ for 1:Fixnum - nie rozumiem.

jeśli jakaś zmienna nie jest podana we wzorcu, jest dodawana po ?

map.connect "bizuteria/:name.html", :controller => 'jewelry', :action => 'show'

masz podaną zmienną :name, ale nie masz :id -więc :id będzie występował jako ?id=cos

map.show_jewelry "bizuteria/:slug.html?id=:id", :controller => 'jewelry', :action => 'show'

zamień na:

map.show_jewelry "bizuteria/:slug.html", :controller => 'jewelry', :action => 'show'

i przekazuj normalnie id, wtedy otrzymasz link w postaci bizuteria/costam.html?id=cos
choc nie wiem ,czy ladniej by nie wygladalo:

map.show_jewelry "bizuteria/:id-:slug.html", :controller => 'jewelry', :action => 'show'

wtedy otrzymasz linka w postaci:
bizuteria/identyfikator-opis_do_seo.html

Niestety :frowning:

Teraz działa mi http://www.example.com/bizuteria/lancuszek-zloty-serce/44.html

map.show_jewelry "bizuteria/:slug/:id.html", :controller => 'jewelry', :action => 'show'

i buduję w różnych miejscach automatycznie linki za pomocą:

<%= link_to jewelry.name, show_jewelry_path(jewelry.url_name, jewelry.id) -%>

Jednak dla przykładów które podałeś, dostaję błąd: undefined method `has_key?’ for 1:Fixnum dla drugiego argumentu show_jewelry_path z powyższego kodu (1 z tego błędu to pierwsze id pobrane z bazy). Co do samej budowy adresu zgadzam się, rozwiązanie które zaproponowałeś jest lepsze :slight_smile: Jednak czemu dostaję taki błąd?

Co najdziwniejsze, adres /bizuteria/4-a-tu-jej-jakis-opis-seo.html działa dla reguły:

map.show_jewelry "bizuteria/:id.html", :controller => 'jewelry', :action => 'show'

Jednak wtedy też przy budowaniu adresów opisanym wyżej dostaję ten sam błąd :frowning: Czy ktoś wie czemu?

Jakiej wersji Rails używasz ? Pod 2.3.2 ostatni przykład podany przez Ciebie generuje u mnie poprawnie url’a:

http://localhost:3000/bizuteria/jakis-tekst/1.html

Rails 2.3.2 - i masz rację ten przykład generuje poprawnie urla, dopiero po zmianie reguł w routes (na takie jak w moim przykładzie) pojawia się problem z generacją url’a.

Tzn, wszystko co opisałeś w swojej odpowiedzi wyżej działa jak trzeba, ale chcę zmienić jeszcze adresację na: /bizuteria/id-jakas-nazwa.html (zamiast /bizuteria/costam-costam/id.html) - i wtedy wywala się metoda do tworzenia urla.

map.show_jewelry "bizuteria/:id-:slug.html", :controller => 'jewelry', :action => 'show

Przy generowaniu url’a podaj najpierw id a pozniej slug, czyli:

link_to “test”, show_jewelry_path(1, ‘test’)

Musi działać :slight_smile:

Prawie jesteśy w domu już, ale jeszcez coś jest nie tak.

dla: link_to “test”, show_jewelry_path(1, jewelry.url_name) dostaję: undefined method `has_key?’ for “Zloty-Lancuszek”:String ()

adres: /bizuteria/3-:slug.html - pokazuje biżuterię o id 3 - tak jak trzeba
adres: /bizuteria/3-byleco.html - No route matches “/bizuteria/3-byleco.html” with {:method=>:get}

Czyli jest problem z :slug w definicjach routes.rb - jakiś pomysł?

Rozwiązanie pierwsze:

map.show_jewelry "bizuteria/:id-:slug.html", :controller => 'jewelry', :action => 'show', :requirements => {:id => /\d+/}

Rozwiązanie drugie:

[code=Ruby]# w config/routes.rb
map.resources :jewelry

w app/models/jewlery.rb:

def to_param
“#{id}-#{url_title}”
end[/code]
I wtedy tworzymy linki normalnie przez

[code=Ruby]@jewlery = Jewlery.first # whatever…

link_to “test”, jewelry_path(@jewelry, :html) #=> /bizuteria/1-costam.html[/code]
Opis metody to_param.

Drugie rozwiązanie mi działa jeżeli dodam regułę:

map.show_jewelry "bizuteria/:id.html", :controller => 'jewelries', :action => 'show'

Bez tego buduje mi ścieżkę z /jewelries/5-nazwa.html - a potrzebuję polskiej nazwy tutaj. Tak czy inaczej to krok do przodu, dzięki :slight_smile:

Możesz też dodać parametr :as do nazwy zasobu w pliku config/routes.rb:

map.resources :jewelry, :as => "bizuteria"

Wtedy ścieżki będą miały postać “bizuteria/5-costam.html”

Polecam przeczytanie dokumentacji metody resources.