Rails url_for and namespaced models
In Rails, is it possible to namespace models in modules and still get correct behavior from url_for
?
For instance, here, url_for
works as expected:
# 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
Whereas after putting the User
model into a module, url_for
complains about an undefined method 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'
Is it possible to have url_for
ignore the module in M::User
and return user_path
for url_for(@user)
instead of m_user_path
?
UPDATE
So, after almost 5 years, here's the solution, thanks to esad. This has been tes开发者_如何学编程ted in 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
Note: when generating model, view and controller with bin/rails g scaffold m/user
, the views and the controller will be namespaced, too. You need to move app/views/m/users
to app/views/users
and app/controllers/m/users_controller.rb
to app/controllers/users_controller.rb
; you also need to remove references to the module M
everywhere except in the model M::User
.
Finally, the goal here was to namespace models but not views and controllers. With esads solution, the module M
(containing User
) is explicitly told to not appear in routes. Thus, effectifely, the M
is stripped of and only User
remains.
The user model can now reside in app/views/models/m/user.rb
, the users controller lives in app/views/controllers/users_controller.rb
and the views can be found in app/views/users
.
Just define use_relative_model_naming?
in the containing module to avoid prefixing the generated route names:
module M
def self.use_relative_model_naming?
true
end
end
Use
namespace "blah" do
resources :thing
end
Then routes will be named appropiately.
rake routes
To view all routes
Specify the module on the route
resources :users, :module => "m"
or use scope to do it
scope :module => "m" do
resources :users
end
In my case I overridden the url_for method on my application_helper.rb file to add the :network param on all routes from my namespace :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
精彩评论