2010-09-07 12 views
16

Mi chiedevo se esistessero plugin o metodi che mi permettessero di convertire percorsi di risorse che mi permettessero di posizionare il nome del controller come sottodominio.Rails Restful Routing and Subdomains

Esempi:

map.resources :users 
map.resource :account 
map.resources :blog 
... 

example.com/users/mark 
example.com/account 
example.com/blog/subject 
example.com/blog/subject/edit 
... 

#becomes 

users.example.com/mark 
account.example.com 
blog.example.com/subject 
blog.example.com/subject/edit 
... 

mi rendo conto che posso fare questo con percorsi denominati ma chiedevano se ci fosse un modo per mantenere il mio file routes.rb attualmente succinta.

+2

Ho aggiunto una taglia di 100 rep per questo - sto incontrando un dilemma simile, quindi una risposta valida sarebbe grande. – Jeriko

+0

Quale versione di Rails? 2.xo 3? – tommasop

+0

Nel mio caso, 2.3, anche se jeriko merita più attenzione su questo ora. – mark

risposta

3

Il modo migliore per farlo è quello di scrivere una libreria middleware semplice rack che riscrive le intestazioni di richiesta in modo che la tua app per i binari ottenga l'url che ti aspetti, ma dal punto di vista dell'utente l'url non cambia. In questo modo non è necessario apportare modifiche alla applicazione Rails (o il file di rotte)

Ad esempio, il lib cremagliera sarebbe riscrivere: users.example.com => example.com/users

Questo gemma dovrebbe fare esattamente questo per voi: http://github.com/jtrupiano/rack-rewrite

AGGIORNATO CON CODICE ESEMPIO

Nota: questo è rapidamente scritto, completamente testato, ma dovrebbe impostare voi sulla strada giusta. Inoltre, non ho controllato la gemma cremagliera-rewrite, che potrebbe rendere questo ancora più semplice

# your rack middleware lib. stick this in you lib dir 
class RewriteSubdomainToPath 

    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    original_host = env['SERVER_NAME'] 
    subdomain = get_subdomain(original_host) 
    if subdomain 
     new_host = get_domain(original_host) 
     env['PATH_INFO'] = [subdomain, env['PATH_INFO']].join('/') 
     env['HTTP_X_FORWARDED_HOST'] = [original_host, new_host].join(', ') 
     logger.info("Reroute: mapped #{original_host} => #{new_host}") if defined?(Rails.logger) 
    end 

    @app.call(env) 

    end 

    def get_subdomain 
    # code to find a subdomain. simple regex is probably find, but you might need to handle 
    # different TLD lengths for example .co.uk 
    # google this, there are lots of examples 

    end 

    def get_domain 
    # get the domain without the subdomain. same comments as above 
    end 
end 

# then in an initializer 
Rails.application.config.middleware.use RewriteSubdomainToPath 
+0

Questo ha più senso per me, dal momento che l'accento è posto sull'essere riposati. Se riesci a elaborare un po 'di più, magari con un esempio di codice, ti darò la taglia. Questo metodo avrebbe qualche potenziale problema con i cookie? – Jeriko

+0

Aggiornato con un esempio di codice. I cookie dovrebbero andare bene in quanto tutte le richieste arriveranno allo stesso dominio di base per quanto riguarda l'app delle tue guide. A meno che non si stia tentando di mantenere diversi set di cookie per ciascun utente. – Nader

+0

Dannazione: sembra che la ricompensa sia scaduta prima che potessi assegnartela. Non sono sicuro se è completamente perso o se c'è qualcosa che posso fare per recuperarlo, scoprirò .. – Jeriko

5

Penso che il plug-in subdomain-fu sia esattamente quello che ti serve. Con esso si sarà in grado di generare percorsi come

map.resources :universities, 
    :controller => 'education_universities', 
    :only => [:index, :show], 
    :collection => { 
     :all => :get, 
     :search => :post 
    }, 
    :conditions => {:subdomain => 'education'} 

Questo genererà il seguente:

education.<your_site>.<your_domain>/universities GET 
education.<your_site>.<your_domain>/universities/:id GET 
education.<your_site>.<your_domain>/universities/all GET 
education.<your_site>.<your_domain>/universities/search POST 
+0

Ciao Igor e grazie per la tua risposta. Ho esaminato il sottodominio, ma il problema è che aggiunge effettivamente un namespace come nome del sottodominio, piuttosto che usare il nome del controller che è quello che speravo. Nel tuo esempio desidererei abbandonare l'istruzione e spostare le università (il nome del controller) come sottodominio. – mark

+0

Ciao Mark, ora ho lo stesso problema ed è quello che ho fatto. Ho creato il namespace Education, con parametri: name_prefix => '' e: path_prefix => ''. In questo spazio dei nomi puoi fare quello che vuoi, ho diversi spazi dei nomi aggiuntivi al suo interno. Ma per ogni percorso al suo interno, devi aggiungere: condizioni => {: sottodominio => 'educazione'}. Non so, come scrivere meglio, ma penso che funzioni bene. Se vuoi, contattami e ti mostrerò. –

0

Ryan Bates copre questo nel suo Railscast, Subdomains.

+1

Scusa Yasky, il Railscast non si rivolge in modo specifico ai sottodomini restful, e finisce per essere un po 'vago. Non il mio -1, però. – Jeriko

3

Ciò è possibile senza utilizzare plug-in.

data la struttura di directory app/controllers/portal/customers_controller.rb e voglio essere in grado di chiamare aiutanti URL prefisso portal, cioè new_portal_customer_url. E l'URL sarà accessibile solo tramite http://portal.domain.com/customers. Quindi ... usare questo:

constraints :subdomain => 'portal' do 
    scope :module => 'portal', :as => 'portal', :subdomain => 'portal' do 
    resources :customers 
    end 
end 
2

Come accennato ileitch si può fare questo senza gemme in più è davvero semplice in realtà.

Ho un rotaie freschi applicazione di serie con un'impalcatura utente fresco e un controller cruscotto per la mia amministrazione così mi basta andare:

constraints :subdomain => 'admin' do 
    scope :subdomain => 'admin' do 
     resources :users 

     root :to => "dashboard#index" 
    end 
end 

Quindi questo va da questo:

  • site.com/utenti

a questo:

  • admin.site.it/utenti

è possibile includere un'altra radice: to => "{controller} # {azione}" al di fuori di tale vincolo e ambito per sito.com che potrebbe essere un controller di pagine. Che sarebbe ottenere questo:

constraints :subdomain => 'admin' do 
    scope :subdomain => 'admin' do 
     resources :users 

     root :to => "dashboard#index" 
    end 
end 

root :to => "pages#index" 

Questo sarà quindi risolvere:

  • site.com
  • admin.site.com
  • admin.site.com/users