# Controllo degli URL nel routes.rb

**URL:** <https://www.ruby-forum.com/t/controllo-degli-url-nel-routes-rb/204681>\
**Category:** IT\
**Created:** [March 18, 2011, 2:46pm UTC](https://www.ruby-forum.com/t/controllo-degli-url-nel-routes-rb/204681 "2011-03-18T14:46:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 18, 2011, 2:46pm UTC](https://www.ruby-forum.com/t/controllo-degli-url-nel-routes-rb/204681/1 "2011-03-18T14:46:53Z")

</div>

Salve ragazzi Vi prego aiutatemi,

avrei bisogno di capire come evitare che l’applicazione generi le pagine  
se l’url richiesto è “sbagliato”.

Mi spiego meglio nel mio rotes.rb ho il seguente codice:

map.software ‘:id/software/:keyword/:title.html’,  
:controller=\>‘view’,  
:action=\>‘programma’

dato che la :keyword e il :title vengono generate automaticamente con il  
seguente codice:

software\_url(:id=\>guide.id,:keyword=\>guide.subcategory.name,:title=\>guide.title.split.join(“-”).downcase)

se nell’url metto una qualsiasi altra parola nella posizione di :keyword  
oppure di :title mi viene mostrata comunque la pagina originaria legata  
all’:id.

Insomma, per capirci, provate ad aprire il seguente link:

[http://www.software-windows.net/99/software/firewall/r-firewall.html](http://www.software-windows.net/99/software/firewall/r-firewall.html)

e a modificare la parola firewall oppure r.firewall.

Ho necessità di risolvere il problema perché ogni tanto mi trovo che  
google mi dà pagine con contenuto duplicato…

Grazie mille per l’aiuto

---

<div class="post-metadata">

**Author:** ![softwarewin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@softwarewin](https://www.ruby-forum.com/u/softwarewin)\
**Post date:** [March 18, 2011, 3:11pm UTC](https://www.ruby-forum.com/t/controllo-degli-url-nel-routes-rb/204681/2 "2011-03-18T15:11:15Z")

</div>

Ammesso che i valori di keyword e title non ti servano, esistano cio  
solo  
per comporre la URL, il mio consiglio di evitare di sporcare il file di  
routing.

Puoi benissimo sovrascrivere il metodo ActiveRecord::Base#to\_param e  
fargli  
ritornare il path che serve a te.

Ad esempio

```
class Guide < ActiveRecord::Base
  def to_param
    if persisted?
      "#{id}/#{subcategory.name.parameterize}/#{title.parameterize}"
    else
      super
    end
  end
end

```

A quel punto ti baster passare

```
software_url(:id => guide.to_param)

```

dopo aver cambiato la regola di routing in

```
map.software ':id', :controller => 'view', :action => 'programma'

```

Nota che l’uso di / nella generazione di path potrebbe andare in  
conflitto  
con le impostazioni di default di routing di Rails. Motivo per cui in  
genere  
si consiglia l’uso di -.  
Vedi questo screencast

> **[\#63 Model Name in URL - RailsCasts](http://railscasts.com/episodes/63-model-name-in-url)**
>
> Short Ruby on Rails screencasts containing tips, tricks and tutorials. Great for both novice and experienced web developers.

In tal caso puoi passare un diverso requirement al parametro :id nella  
route.

```
map.software ':id', ... , :id => /.*/

```

Personalmente lo sconsiglio poich potrebbe andare in conflitto con altri  
sistemi.

Altra cosa. Preferisci sempre l’uso delle risorse. In questo caso non c’  
motivo per cui tu non le debba scegliere.

```
map.resources :software

software_path(guide)

```

Il vantaggio che se usi le convenzioni, Rails funziona molto meglio.

Altro consilio. Evita catene di metodi come  
“guide.title.split.join(”-“).downcase” poich la possibilit che generino  
bug direttamente proporzionale al numero di metodi che hai in catena.  
Un  
codice cos poi molto complesso da testare e questo mi lascia pensare  
che  
tu non abbia creato un test che validi il costrutto. Al posto, crea un  
metodo nella class Guide.

In questo caso, puoi rimpiazzare il “split.join(”-“).downcase” con un  
nice  
#parameterize offerto da Rails senza bisogno di un metodo aggiuntivo. In  
linea di massima, evita elaborazioni molto complesse on-the-fly quando  
chiami altri metodo, altrimenti se dovrai generare quel path altrove  
dovrai  
duplicare la logica di esecuzione.

Dulcis in fundo, arriviamo al punto fondamentale. Per impedire la  
duplicazione delle route il consiglio che ti d di eseguire una verifica  
nel controller. In teoria la puoi eseguire anche ora, ma il motivo per  
cui  
ho sottolienato l’uso di #to\_param e delle risose perch la rende molto  
pi semplice.

Il controllo si basa sul verificare che l’URL chiamato sia quello che  
normalmente la pagina comporrebbe, in alternativa reindirizzare a quello  
corretto impostando un 301. Ecco un esempio (d per assunto che #show sia  
la  
action che mostra il programma, che nel tuo caso si chiama programma.  
Personalmente sconsiglio nel modo pi assoluto di mischiare italiano con  
inglese, soprattutto in Rails)

```
class GuidesController

  before_filter :find_guide, :only => %( show )
  before_filter :validate_url, :only => %( show )

  def show
    # ...
  end

  private

    def find_guide
      # Importante: nel caso tu adotti una struttura dove
      # il parametro :id "sporcato" da altri valori, assicurati
      # che il find avvenga correttamente.
      @guide = Guide.find(params[:id])
    end

    def validate_url
      if request.request_uri != guide_path(@guide)
        # rigenero il path utilizzando url poich i redirect
        # dovrebbero per RFC contenere sempre URI assoluti
        redirect_to guide_url(@guide), :status => 301
      end
    end

end

```

Il codice un prototype. L’ho scritto al volo senza test e senza la  
versione di Rails (ad esempio Rails 3 mi pare abbia deprecato  
request.request\_uri) quindi perdona eventuali errori. Ad ogni modo,  
dovrebbe  
darti diversi spunti di approfondimento.

–  
Simone C.  
Application Developer

Site & Blog: [http://www.simonecarletti.com](http://www.simonecarletti.com)  
Email: removed\_email\_address@domain.invalid  
LinkedIn: [http://linkedin.com/in/weppos](http://linkedin.com/in/weppos)  
Skype: weppos
