Rails namespaces and routing - ruby-on-rails

I need help. I want administration for my rails application. I tried to set the routes with namespaces, but namespaces require a resource, and resource must have id in get request.
Anybody know how to set up correctly? I using windows machine. Thanks.
My routes :
Web::Application.routes.draw do
namespace :admin do
resources :access # GET http://localhost/admin/access/login/login - stupid??
end
match ':controller(/:action(/:id))(.:format)'
end

Try to use resource :access instead of resources :access
namespace :admin do
resource :access
end
It will generate routes:
admin_access POST /admin/access(.:format) admin/access#create
new_admin_access GET /admin/access/new(.:format) admin/access#new
edit_admin_access GET /admin/access/edit(.:format) admin/access#edit
GET /admin/access(.:format) admin/access#show
PUT /admin/access(.:format) admin/access#update
DELETE /admin/access(.:format) admin/access#destroy

namespace :admin do
get "login" => "access#login", :as => :login # GET http://localhost/admin/login - admin_login_path
end

If you don't have a set of restful resources, but just want a set of different controller methods, here's one way you can do it:
scope '/admin' do
get '' => "admin#index", :as => 'admin_home'
get '/users' => 'admin#users', :as => 'admin_users'
get '/other_admin_task' => 'admin#other_admin_task', :as => 'other_admin_task'
end

Related

Application Helper Methods Availability

I am using Rails 4 and am trying to include the koudoku stripe gem. Here is my routes:
# Added by Koudoku.
mount Koudoku::Engine, at: 'koudoku'
scope module: 'koudoku' do
get 'pricing' => 'subscriptions#index', as: 'pricing'
end
resource :account
devise_for :users, :skip => [:sessions]
as :user do
get '/login' => 'devise/sessions#new', :as => :new_user_session
post '/login' => 'devise/sessions#create', :as => :user_session
get '/logout' => 'devise/sessions#destroy', :as => :destroy_user_session
end
get '/dashboard', to: 'dashboard#index'
get '/reports/generate', to: 'reports#generate'
authenticated :user do
root :to => 'dashboard#index', :as => :authenticated_root
end
root :to => redirect('/login')
And this is the error I am getting:
undefined local variable or method `root_url
I can access the other routes just fine, it is just trying to render the Application Helper methods (for instance, a custom app method I have defined, or routes methods) from the module routes... Does this make sense? How do I fix this?
Try adding "main_app." before your root path. For example:
main_app.root_path
Conditional logic in the routing layer kind of goes against the intent of the Rails MVC architecture. The route file should just map a web request to a controller, which then has conditional logic to determine what is displayed.
In this case it's a bit different since you want to redirect, but I personally would still put it in the controller. In other words send the root to dashboard#index, and then at the top of that controller (or in a before_filter) just do
redirect_to login_path unless current_user_authenticated?
(here I'm assuming you would have a named route for login, which would be good practice, as well as a current_user_authenticated? method to check whatever logic you want before the redirect. This would be a more Rails-y approach, whatever that's worth...)

Rails: Define routes manually after modifying to_param

I have been trying to implement a vanity url for user profiles, based on the example here: Rails 3: Permalink public profile. I have replaced the 'id' with username:
def to_param
username
end
However this has caused issues with my other routes. I have set them so that they match the default sets of routes exactly, when running 'rake routes'.
get '/users/' => 'users#index', :as => :users
post '/users' => 'users#create'
get '/users/new' => 'users#new', :as => :new_user
get '/users/:id/edit' => 'users#edit', :as => :edit_user
patch '/users/:id' => 'users#update'
put '/users/:id' => 'users#update'
delete '/users/:id' => 'users#destroy'
# for vanity url
get '/:id' => 'users#show', :as => :user
With this setup, trying to access delete and update routes give me 'no route matches' error. What is the proper way to specify these, and / or should I be doing this a different way? Any help is appreciated.
I think it's interresting and more readable to keep the resources syntax in the routes.rb, except for the show, which you can rewrite to customize user_path :
resources :users, :except => [:show]
# 2 possibilities for the show url
get '/users/:id' => 'users#show' # can be removed if you don't want to keep /users/:id url
get '/:id' => 'users#show', :as => :user
But change the controller to find user by username instead of id, for example
def show
#post = Post.find_by_username(params[:id]) # instead of Post.find(params[:id])
# ...
end

Can't figure out how Rails route helper should look

I am working on an assignment which includes adding a feature to Typo.
rake routes shows:
admin_content /admin/content {:controller=>"admin/content", :action=>"index"}
/admin/content(/:action(/:id)) {:action=>nil, :id=>nil, :controller=>"admin/content"}
I need to create a route helper which matches the following RESTful route: /admin/content/edit/:id and an example of url is /admin/content/edit/1
But I can't figure out how to do it. I tried something like admin_content_path(edit,some_article) but it didn't work. (some_article is just an article object)
In routes.rb file:
# some other code
# Admin/XController
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
match "/admin/#{i}(/:action(/:id))", :to => "admin/#{i}", :action => nil, :id => nil, :format => false
end
#some other code
Thanks a lot for your help!
If you are using RESTful routes, why not use the Rails default routes?
So your routes.rb would look like
namespace :admin do
resources :content
resources :advanced
resources :categories
resources :comments
...
<etc>
end
This does assume all your controllers are in the folder admin (but from your comment this seems to be the case.
If you do that, you can just use the standard route-helper: edit_admin_content_path.
If you want to do it manually, you should try adding a name to your route. E.g. as follows:
match "/admin/#{i}/:action(/:id)" => "admin/#{i}", :as => "admin_#{i}_with_action"
and then you should do something like
admin_content_with_action(:action => 'edit', :id => whatevvvva)
As a side-note: I really do not like the meta-programming in your config/routes.rb, if for whatever you really find that the default resources are not a right fit, I would advise to use methods instead (as explained here)
So for example in your config/routes.rb you would write:
def add_my_resource(resource_name)
match "/#{resource_name}", :to => "#{resource_name}#index", :format => false
match "/#{resource_name}(/:action(/:id))", :to => "#{resource_name}", :as => 'admin_#{resource_name}_with_action", :action => nil, :id => nil, :format => false
end
namespace :admin do
add_my_resource :content
add_my_resource :advanced
add_my_resource :categories
...
end
which imho is much more readable.
But my advice, unless you really-really need to avoid it, would be to use the standard resources since you do not seem to add anything special.
HTH.

Typus route order

It used to be that you could load Typus routes exactly where you needed them by placing
Typus::Routes.draw(map)
at the appropriate point in your routes.rb file. It seems that this is no longer supported and that they're always loaded after all of the application routes. This causes problems with catchall routes which must be defined last. Does anyone know how to control the load order for typus now? Is there a way to get them defined before any of the app routes rather than after? Thanks!
I got around it by leaving my catch-all routes at the end of my apps routes.rb BUT excluding it from matching for Typus urls:
# A catch all route
match '*path' => 'content#show', :constraints => lambda{|request|
!request.path.starts_with?("/admin") # excluded if typus will be taking it...
}
This may or may now work for you...
I'm looking for the same answer.
At the moment I have resorted to copying the contents from typus's config/routes.rb and placing it into my routes.rb file, before the catchall route.
It's a horrible, hackish solution, but it's solving my immediate problem.
Example:
# TODO: KLUDGE: MANUALLY BRING THE TYPUS ROUTES IN
# Typus used to provide :
# Typus::Routes.draw(map)
# But that is no longer the case.
scope "admin", :module => :admin, :as => "admin" do
match "/" => "dashboard#show", :as => "dashboard"
match "user_guide" => "base#user_guide"
if Typus.authentication == :session
resource :session, :only => [:new, :create, :destroy], :controller => :session
resources :account, :only => [:new, :create, :show, :forgot_password] do
collection do
get :forgot_password
post :send_password
end
end
end
Typus.models.map { |i| i.to_resource }.each do |resource|
match "#{resource}(/:action(/:id(.:format)))", :controller => resource
end
Typus.resources.map { |i| i.underscore }.each do |resource|
match "#{resource}(/:action(/:id(.:format)))", :controller => resource
end
end
# END KLUDGE
# Catch all to the state page handler
match '/:page' => 'pages#show', :as => 'page'

Rails 3 routing - what's best practice?

I'm trying out Rails, and I've stumbled across an issue with my routing.
I have a controller named "Account" (singular), which should handle various settings for the currently logged in user.
class AccountController < ApplicationController
def index
end
def settings
end
def email_settings
end
end
How would I set-up the routes for this in a proper manner? At the moment I have:
match 'account(/:action)', :to => 'account', :as => 'account'
This however does not automagically produce methods like account_settings_path but only account_path
Is there any better practice of doing this? Remember the Account controller doesn't represent a controller for an ActiveModel.
If this is in fact the best practice, how would I generate links in my views for the actions? url_to :controller => :account, :action => :email_settings ?
Thanks!
To get named URLs to use in your views, you need to specify each route to be named in routes.rb.
match 'account', :to => 'account#index'
match 'account/settings', :to => 'account#settings'
match 'account/email_settings', :to => 'account#email_settings'
Or
scope :account, :path => 'account', :name_prefix => :account do
match '', :to => :index, :as => :index
match 'settings', :to => :settings
match 'email_settings', :to => :email_settings
end
Either works the same, it's just a matter of choice. But I do think the first method is the cleanest even if it isn't as DRY.
You could also define it as a collection on the resource:
resources :login do
collection { get :reminder, :test }
end
Of course, this also defines the default CRUD actions as well. I'm currently only using two of those for my not-an-actual-model controller, but I don't think/expect there will be any problem with the extra routes.

Resources