2010-12-10 11 views
13

En Rails, ¿es posible crear espacios de nombres en módulos y aún así obtener el comportamiento correcto de url_for?Rails url_for y namespaced models

Por ejemplo, aquí, url_for funciona como se espera:

# app/models/user.rb 
class User < ActiveRecord::Base 
end 

# config/routes.rb 
resources :users 

# app/views/users/index.html.haml 
= url_for(@user) # /users/1 

Mientras que después de poner el modelo User en un módulo, url_for se queja de un método no definido m_user_path:

# app/models/m/user.rb 
module M 
    class User < ActiveRecord::Base 
    end 
end 

# config/routes.rb 
resources :users 

# app/views/users/index.html.haml 
= url_for(@user) # undefined method 'm_users_path' 

¿Es posible tener url_for ignorar el módulo en M::User y devolver user_path para url_for(@user) en lugar de m_user_path?

ACTUALIZACIÓN

Así, después de casi 5 años, aquí está la solución, gracias a ESAD. Esto ha sido probado en Rails 4.2.

# app/models/m/user.rb 
module M 
    class User < ActiveRecord::Base 
    end 
end 

# app/models/m.rb 
module M 
    def self.use_relative_model_naming? 
    true 
    end 
    def self.table_name_prefix 
    'm_' 
    end 
end 

# config/routes.rb 
resources :users 

# app/views/users/index.html.haml 
= url_for(@user) # /users/1 

Nota: cuando se genera el modelo, vista y controlador con bin/rails g scaffold m/user, serán de espacios de nombres de las vistas y el controlador, también. Debe mover app/views/m/users a app/views/users y app/controllers/m/users_controller.rb a app/controllers/users_controller.rb; también debe eliminar las referencias al módulo M en todas partes, excepto en el modelo M::User.

Finalmente, el objetivo aquí era para los modelos de espacio de nombres pero no para las vistas y los controladores. Con la solución de búsqueda, el módulo M (que contiene User) se le indica explícitamente que no aparezca en las rutas. Por lo tanto, de manera efectiva, se elimina el M y solo queda User.

El modelo de usuario ahora puede residir en app/views/models/m/user.rb, el controlador de usuario vive en app/views/controllers/users_controller.rb y las vistas se pueden encontrar en app/views/users.

Respuesta

23

Simplemente defina use_relative_model_naming? en el módulo que contiene para evitar prefijo de los nombres de ruta generados:

module M 
    def self.use_relative_model_naming? 
    true 
    end 
end 
+0

Esto es de oro! Resuelve exactamente lo que el OP estaba pidiendo (y lo que estaba buscando) Gracias – Ivar

+0

¡Si pudiera poner más + 1 aquí !!!!! ¡Gracias! – eirc

+0

¡Este método debería ser el primero documentado en la API de Rails! – olhor

4

Uso

namespace "blah" do 
    resources :thing 
end 

Entonces rutas se llamará apropiadamente.

rake routes 

Para ver todas las rutas

+0

Gracias, lo he intentado, pero no resuelve el problema: aunque url_for consigue informados sobre el modelo de espacio de nombres, se adaptarán las rutas (controladores) para utilizar el mismo espacio de nombres - que no es lo que necesito. Por lo tanto: ¿es posible configurar rutas para usar modelos y controladores que viven en diferentes espacios de nombres? En otras palabras, ¿hay alguna manera de influir en el comportamiento de url_for dada una instancia modelo, sin tocar las rutas del controlador? Por ejemplo, el modelo M :: Usuario se definiría en la aplicación/modelos/m/user.rb, mientras que el controlador se definiría en la aplicación/controladores/user_controller.rb. – sebastian

+0

Además, ¿qué haces si no es un recurso RESTFul? Tengo este problema y el controlador con el que trato no se puede meter en un recurso. – Ibrahim

+0

resources: things do (nueva línea) get "foo" => "controller # action". – sethvargo

3

Especificar el módulo sobre la ruta

resources :users, :module => "m" 

o utilizar el alcance de hacerlo

scope :module => "m" do 
    resources :users 
end 
+0

¡Funciona a la perfección! Gracias :) – Volte

0

En mi caso se reemplaza el método url_for en mi archivo application_helper.rb para añadir el: param red en todas las rutas de mi espacio de nombres: MKP.

module ApplicationHelper 
    def url_for(options = {}) 
    if options.is_a?(Hash) && options.has_key?(:controller) 
     if options[:network].nil? && options[:controller].match(/^mkp\//).present? 
     options[:network] = @network.downcase 
     end 
    end 
    super(options) 
    end 
end 
Cuestiones relacionadas