Application Helper Methods Availability - ruby-on-rails

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

Related

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

ruby custom routes

I am new to ruby on rails.
Here is my routes.rb
RpxNowExample::Application.routes.draw do
root :to => "users#index"
resources :users
end
Normally my functionality is working fine, but I want to make a tweak. I want it to redirect to another view "promptemail" using the same controller calling another action if a condition is true i.e
if(#provider == "Twitter")
redirect_to :action => :promptemail
end
It should take me to that promptemail view.
You can pass a block to your resources definition to add extra actions outside of the standard:
resources :users do
match :promptemail, :via => [:get], :on => :member
end
The :via option allows you to restrict on get, post, put etc, the :on parameter will take either :member, or :collection.
:collection will operate on a collection, so similar to the index action, :member will operate on an individual record. As such if you specify your route as :on => :member, you will need to provide an object or id when you generate the route.
More info about adding routes to resources can be found here: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
Using the same controller calling another action-
Try:
routes.rb:
RpxNowExample::Application.routes.draw do
root :to => "users#index"
resources :users do
collection do
get 'promptemail'
end
Your controller:
if(#provider == "Twitter")
redirect_to :promptemail
end
Note: - No need to call action in redirect_to as you are calling the action within the same controller.

How can I redirect multiple devise model to multiple specific urls?

I got three independent devise models, ergo I got three different sign_in screen. And all three have got a dashboard:
devise_for :md1
devise_for :md2
devise_for :md3
match 'md1/dashboard' => 'md1#dashboard', :via => :get
match 'md2/dashboard' => 'md2#dashboard', :via => :get
match 'md3/dashboard' => 'md3#dashboard', :via => :get
I want when there is a mdX succesfully sign in, it will redirect to mdX#dashboard, and if it is possible by GET. I tried:
devise_scope :md1 do
root :to => 'md1#dashboard'
end
devise_scope :md2 do
root :to => 'md2#dashboard'
end
devise_scope :md3 do
root :to => 'md3#dashboard'
end
Then when I succesfully sign in with md1 I got redirected to md1 dashboard, but when I succesfully sign in with md2 I got redirected to md1's sign_in screen.
Then I tried:
def after_sign_in_path_for resource
dashboard_path resource
end
But there isn't such method. Is there an easy way to do this or it has to be with the if statements for each model?
UPDATE
Some routes to make a better understanding and more information to get a better solution
md1_dashboard GET /md1/dashboard(.:format) md1#dashboard
md2_dashboard GET /md2/dashboard(.:format) md2#dashboard
md3_dashboard GET /md3/dashboard(.:format) md3#dashboard
Thanks in advance
When you are writing this:
devise_scope :md1 do
root :to => 'md1#dashboard'
end
devise_scope :md2 do
root :to => 'md2#dashboard'
end
devise_scope :md3 do
root :to => 'md3#dashboard'
end
You are defining three root routes, with the same name. Since they conflict, only the first will be used. That's why only md1 worked. You probably meant to write this:
scope :md1 do
root :to => 'md1#dashboard'
end
scope :md2 do
root :to => 'md2#dashboard'
end
scope :md3 do
root :to => 'md3#dashboard'
end
On this case, you will define three different root routes, at three different scopes (check rake routes again). Note scope is a router method that scopes your routes, devise_scope does not scope any route, it simply tells which devise scope you want to use, which you don't need to tell unless Devise explicitly asks you so (you will know when it does).
After this change, everything should work as expected. Note that Devise by default uses #{scope}_root_path to redirect after successful sign in, that's why the code above works (check rake routes and you will see you md1_root, md2_root, etc are now defined).

Rails namespaces and routing

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

error setting user_root for devise redirect

Goal
When user submits the devise "edit registration" form, I want to redirect to users#show rather than the site's root.
Problem
Following Devise's instructions has not worked. I don't want to customize the Devise controller, so I'm left with two suggested modifications to routes.rb, either
devise_for :users do
get 'users', :to => 'users#show', :as => :user_root
end
or
match 'user_root' => 'users#show'
The first redirects to http://localhost:3000/users after submitting the edit form, the second redirects to http://localhost:3000/user_root. Both give the same error, "Couldn't find User without an ID".
My users#show page normally works in the app, so it's not an error with the controller method (or view, of course). It seems to be a routing error. I have "resources :users" in my routes.rb file, nothing else regarding users. If I need to give more information please let me know!
Question
Why isn't the user id being passed in the url?
Have you considered making the action a member action? this will ensure that the url format is controller//action. I don't know if you can even use the member thing in the devise route definition, but that's where I'd start.
devise_for :users do
member do
get 'users', :to => 'users#show', :as => :user_root
end
end
The member part doesn't work but if you take that out it is working for me. +1 to jaydel for close enough :P
devise_for :users do
get 'users', :to => 'users#show', :as => :user_root
end
Another thing that I tried which also worked was :
devise_scope :user do
get 'users' => 'users#show', :as => :user_root
end

Resources