2010-09-07 15 views
16

Me pregunté si habría algún complemento o método que me permitiera convertir rutas de recursos que me permitieran ubicar el nombre del controlador como un subdominio.Rails Restful Routing and Subdominios

Ejemplos:

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 
... 

que se dan cuenta de que puedo hacer esto con rutas con nombre, pero se preguntaban si había alguna manera de mantener mi archivo routes.rb Actualmente sucinta.

+2

He añadido una recompensa de 100 representantes a esto: me encuentro con un dilema similar, por lo que una respuesta viable sería genial. – Jeriko

+0

¿Qué versión de Rails? 2.xo 3? – tommasop

+0

En mi caso, 2.3, aunque jeriko merece más atención sobre esto ahora. – mark

Respuesta

3

La mejor manera de hacerlo es escribir una biblioteca de middleware sencilla estante que reescribe las cabeceras de petición para que su aplicación de rieles obtenga la url que espera pero, desde el punto de vista del usuario, la url no cambia. De esta manera usted no tiene que hacer ningún cambio en su aplicación rieles (o el archivo de rutas)

Por ejemplo, el estante lib sería reescribir: users.example.com => example.com/users

Este gema debe hacer exactamente eso para usted: http://github.com/jtrupiano/rack-rewrite

ACTUALIZADO CON EJEMPLO dE CÓDIGO

Nota: esto está escrito de forma rápida, totalmente probado, pero se debe establecer en el camino correcto. Además, no he comprobado la gema rack de reescritura, lo que podría hacer esto aún más simple

# 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

Esto tiene más sentido para mí, ya que el énfasis está en ser tranquilo. Si puede elaborar un poco más, tal vez con un ejemplo de código, le daré la recompensa. ¿Este método tiene algún problema potencial con las cookies? – Jeriko

+0

Actualizado con un ejemplo de código. Las cookies deberían estar bien ya que todas las solicitudes llegarán al mismo dominio base en lo que respecta a la aplicación de sus rieles. A menos que intente mantener diferentes conjuntos de cookies para cada usuario. – Nader

+0

Maldita sea, parece que la recompensa expiró antes de que pudiera recompensarte. No estoy seguro si está completamente perdido o si hay algo que pueda hacer para recuperarlo, lo averiguaré .. – Jeriko

5

Creo que subdomain-fu plugin es exactamente lo que necesita. Con él usted será capaz de generar rutas como

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

Esto generará el siguiente:

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

Hola Igor y gracias por tu respuesta. He analizado el subdomainfu pero el problema es que efectivamente agrega un espacio de nombres como el nombre del subdominio, en lugar de usar el nombre del controlador que es lo que estaba esperando. En su ejemplo, me gustaría abandonar la educación y mover las universidades (el nombre del controlador) para que sean el subdominio. – mark

+0

Hola Mark, ahora tengo el mismo problema y eso es lo que he hecho. Creé el espacio de nombres Education, con parámetros: name_prefix => '' y: path_prefix => ''. En este espacio de nombres puedes hacer lo que quieras, tengo varios espacios de nombres adicionales dentro de él. Pero para cada ruta dentro de ella, debe agregar: conditions => {: subdomain => 'education'}. No sé cómo escribir mejor al respecto, pero creo que funciona bien. Si quieres, contáctame y te mostraré. –

0

Ryan Bates cubre esto en su Railscast, Subdomains.

+1

Lo siento, Yasky, el Railscast en realidad no aborda subdominios tranquilos específicamente, y termina siendo un poco vago. No es mi -1, sin embargo. – Jeriko

3

Esto es posible sin usar complementos.

Teniendo en cuenta la estructura de directorios app/controllers/portal/customers_controller.rb y quiero ser capaz de llamar ayudantes de URL con el prefijo portal, es decir new_portal_customer_url. Y solo se podrá acceder a la URL a través del http://portal.domain.com/customers. Entonces ... Utilizar este:

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

Como ileitch mencionado se puede hacer esto sin gemas adicionales Es muy simple en realidad.

Tengo una aplicación estándar de rieles frescas con un andamio de usuario nueva y un controlador para mi tablero de administración por lo que sólo tiene que ir:

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

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

Así que esto va de esto:

  • site.com/usuarios

a este:

  • admin.site.com/usuarios

se pueden incluir otra raíz: a = "{controlador} # {acción}"> fuera de esa limitación y el alcance de site.com que podría ser por ejemplo un controlador de páginas. Eso ayudaría a esto:

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

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

root :to => "pages#index" 

Esto entonces resolver:

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