How do you navigate to a users show page with devise? - ruby-on-rails

Like the title says, I am using devise. I want to navigate to /users/1 or whatever the current_users path is. When I try link_to(current_user.name, user_path) I just get an error.
undefined local variable or method `user' for #<#:0x00000101d2dfc8>
Am I not using the right path? Do I need to route it or something?
Also, this goes with the first, how would i navigate to a different users show page(not the current user)

You will need to to three things to get the view you want because devise doesn't provide the standard user routes.
1) Create a route in config/routes.rb. Devise doesn't provide a standard route, and in my experience rake routes just confirms this. I've used:
match '/users/:id', :to => 'users#show', :as => :user, :via => :get
with mixed success
2) Create a user controller with the show section appropriately filled out
3) create a view file: user/show and add the parts you want to show.

I am not familiar with devise, but I'd be surprised if devise differed from Rails conventions. You need to pass in the user to the route helper: link_to(current_user.name, user_path(current_user))

What helped for me was to add the # before user in "routes.rb":
"match 'users/:id' => 'users#show', :as => #user"

Related

Devise Invitable - Restricting Access to Only invited users

I might be searching the wrong key words, but I can't find a way to only restrict users that are invited to be allowed to create an account on my rails site (or maybe I'm using devise-invitable wrong). I assume, there should be a method I call in the before filter or flip the switch on the initializer/devise.rb
I tried in my users_controller.rb and had no luck using Ruby Doc as reference
before_filter: invited?
I have read the initializers/devise.rb and the readme and didn't have any luck.
I think that you should make custom filter for this purpose.
before_action :authenticate_user!
before_filter :restrict_only_invited_users
def restrict_only_invited_users
redirect_to :root if current_user.invitation_accepted_at.blank?
end
I figured out that I didnt think of the obvious. Restrict users via devise with the routes, not devise-invitable.
Used Solution #2 as a reference (see below)
Lets suppose that you don't want to allow to sign up but you want to allow to change password for registered users. Just paste this code in routes.rb:
devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users/:id' => 'devise/registrations#update', :as => 'user_registration'
end
And then you can make such link in your view:
= link_to "Change your password", edit_user_registration_path
Notice: you will need to update default devise views accordingly, i.e. in app/views/devise/registrations/edit.html.erb change registration_path(resource_name) to user_registration_path(resource) (If using shared views for multiple models, you can use send("#{resource_name}_registration_path", resource))
Notice: If you are using rails 4.0+ you should be using patch instead of put for updates. You should change the method in the form_tag residing in app/views/devise/registrations/edit.html.erb and the routes.rb file.

Devise users/sign_in and users/show action trouble

I user devise 3.4.0 under rails 4.1.0.
I want to add user detail page, so I made this route
get 'users/:id' => 'users#show', as: 'user'
But after this, when I access /users/sign_in path, it try to find the user show page.
How to write the right route?
What you did will actually "override" the devise routes (and i think this is the problem you are facing)
If you want to add another route in the scope of devise routes, you have to do something like :
devise_scope :user do
get '/users/:id' => 'users#show'
end
after
devise_for :users
Let me know if it solves the problem !

How to change a rails controller default router from index to other?

As we know, if we have a UsersController, when we get /users it default to /users/index. If I want to map /users to /users/show, what can I do? (This can apply to any other controllers, not just users.)
You can modified the file Global.asax.
There is a method named 'RegisterRoutes',change the 'Index' in 'action=Index' to 'show'
The only difference between URLs for the index action and the show action is the show action requires the identity of the resource. The default Rails URL for index on the users resource is /users, and the default show URL looks like /users/12, where the 12 identifies the resource. This identification part isn't optional, so you can't usefully map /users to the show action in a RESTful scheme.
For example if you want to have a profile page at localhost:3000/username you can add match '/:id' => 'users#show', :as => :user to routes.rb and <%= link_to "Profile", #user %> to your view. With a little fiddling in the controller to grab your profile info via the current user's username, this will link to localhost:3000/username.

Route depending if user is an artist

I'd like to set up my routes depending if the user is an artist. So for example, something like:
namespace 'dashboard' do
if current_user.is_artist
get '/settings', :to => 'users#edit', :as => 'account_settings'
put '/settings', :to => 'users#update', :as => 'account_settings'
delete '/settings', :to => 'users#destroy', :as => 'account_settings'
else
get '/settings', :to => 'artists#edit', :as => 'account_settings'
put '/settings', :to => 'artists#update', :as => 'account_settings'
delete '/settings', :to => 'artists#destroy', :as => 'account_settings'
end
end
Unfortunately, I cannot access current_user in routes.rb. However, the logic of the code above, explains what my intentions are.
Is there a way I can achieve this?
The routing table doesn't run at the context of a specific user. This is because it routes the request before reaching your session management code, so it can't tell who's the current user.
I can think of two solutions:
Render your settings links through some method that rewrites them if the user is an artist. This way 'artists' and 'users' get different URLs.
Add a before_filter to your UserSettings controller that catches requests from artists and redirects them to ArtistSettings (not sure of your internal structure, but you probably get the general idea).
from what you have it looks like you have set up a role called artists. all you have to do to make your current_user method work is: in your account controller you can set up a before filter like saying before_filter :check_user_role :only => :account_setting. then you would set your account_settings for the various roles and their various redirects_to call methods you have. i am working on a similar project and it works for me. i hope this helps you
You could create a piece of middleware that figures out the user on a level before it hits the actual application. This is what warden/devise are doing for example. Add the user object to the env variable and you can access it anywhere lower in the stack.
Your routing file simply determines which controller action is being invoked based on the URL. You can map both artists and users to a single controller, and place the logic for which screen to render in that controller by looking at the user. By default, controllers render a view that is based on the name of the controller and method, but you're free to override this and render whatever view you want. Use your route to dispatch requests to the appropriate edit/update/destroy actions, and put your user/artist logic into those actions to render either the users/edit.html.haml or the artists/edit.html.haml file...
As explained by Elad, the routing itself can not tell if the current user is an artist or not.
If you want to keep a single url with two differents behaviours and views, you may go with a single controller such as :
def settings
if current_user.is_artist
do something
render :action => "artist_settings"
else
do something else
render :action => "users_settings"
end
end

Editing the current User in Rails 3

Users can be edited from a normal resourceful URI like:
/users/1/edit
The issue is that in my application, the edit user page is the home page or root route.
# routes.rb
root :to => "users#edit"
So, I tried to set #user to the current user in the absence of params[:id].
# app/controllers/users_controller.rb
def edit
#user = (params[:id]) ? User.find_by_id(params[:id]) : #current_user
end
Unfortunately, I'm having trouble getting the form to point properly.
# app/views/shared/_manage_users.rb
<%= form_tag follow_user_path, :id => 'update-following-form' %>
I'm getting:
No route matches {:action=>"follow", :controller=>"users"}
follow is a member route of the user resource and has a corresponding controller method. If I access the page via the URI at the top of this question, /users/1/edit, everything works fine and no error is thrown.
I'm not sure whether I'm going about this completely the wrong way or if I'm just not using the right form helper or something silly. How can I fix this issue, or what steps can I follow to debug it?
A member route expects the member to be passed as an argument. You route is expecting a User, like so:
follow_user_path(#user)
in your routes do this
resource :user
instead of
resources :users
now the id param is notin the url. you just need to ensure the user is logged in
I think you need to actually define follow_user in your routes.rb.
Example:
post "user/follow" => "users#follow", :as => :follow_user

Resources