2010-12-10 11 views
13

In Rails, ist es möglich, Namespace-Modelle in Modulen und immer noch richtiges Verhalten von url_for?Schienen url_for und namespaced Modelle

Zum Beispiel hier, url_for funktioniert wie erwartet:

# 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 

Während nach dem User Modell in ein Modul setzen, url_for über eine nicht definierte Methode klagt 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' 

Ist es möglich, have url_for ignorieren Sie das Modul in M::User und geben Sie user_path für url_for(@user) statt 0 zurück?

UPDATE

So, nach fast 5 Jahren, hier ist die Lösung, dank esad. Dies wurde in Rails 4.2 getestet.

# 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 

Hinweis: wenn das Modell zu erzeugen, View und Controller mit bin/rails g scaffold m/user, die Ansichten und die Steuerung auch Namespaces werden. Sie müssen app/views/m/users zu app/views/users und app/controllers/m/users_controller.rb zu app/controllers/users_controller.rb verschieben; Sie müssen auch überall Referenzen auf das Modul M entfernen, außer im Modell M::User.

Schließlich war das Ziel hier Namespace-Modelle, aber keine Ansichten und Controller. Bei der esads-Lösung wird das Modul M (mit User) explizit aufgefordert, nicht in Routen zu erscheinen. Somit ist die M entfernt und nur User bleibt übrig.

Das Benutzermodell kann jetzt in residieren, der Benutzer-Controller lebt in app/views/controllers/users_controller.rb und die Ansichten können in app/views/users gefunden werden.

Antwort

23

definieren zu tun, nur use_relative_model_naming? in dem Aufnahmemodul zu vermeiden Voranstellen der generierten Routennamen:

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

Das ist golden! Löse genau das, was der OP verlangte (und was ich suchte) Danke – Ivar

+0

Wenn ich mehr + 1s hier setzen könnte !!!!! Vielen Dank! – eirc

+0

Diese Methode sollte die erste sein, die in Rails API dokumentiert ist! – olhor

4

Verwenden

namespace "blah" do 
    resources :thing 
end 

Dann werden Routen sachgemässer benannt werden.

rake routes 

Um alle Routen

+0

Danke, habe ich versucht, das, aber es löst nicht das Problem: Obwohl url_for über das Modell Namespace informiert wird, werden die Routen (Controller) angepasst werden, um den gleichen Namensraum zu verwenden - was nicht das, was ich brauche. Also: Ist es möglich, Routen einzurichten, um Modelle und Controller zu verwenden, die in verschiedenen Namespaces leben? Mit anderen Worten, gibt es eine Möglichkeit, das Verhalten von url_ bei einer gegebenen Modellinstanz zu beeinflussen, ohne Controller-Routen zu berühren? Zum Beispiel wäre das Modell M :: User in app/models/m/user.rb definiert, während der Controller in app/controllers/user_controller.rb definiert wäre. – sebastian

+0

Was machst du auch, wenn es keine RESTFul-Ressource ist? Ich habe dieses Problem und der Controller, mit dem ich es zu tun habe, kann nicht in eine Ressource eingeteilt werden. – Ibrahim

+0

Ressourcen: Dinge tun (neue Zeile) bekommen "foo" => "Controller # Aktion". – sethvargo

3

Geben Sie das Modul auf dem

resources :users, :module => "m" 

oder Umfang Route anzuzeigen verwenden Sie es

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

Funktioniert perfekt! Danke :) – Volte

0

In meinem Fall habe ich die Methode url_for in meiner Datei application_helper.rb überschrieben, um den Netzwerkparameter für alle Routen aus meinem Namespace hinzuzufügen: 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 
Verwandte Themen