Rails: How to render different versions of a "show" view - ruby-on-rails

I have a model "User". I defined it in my routes.rb with resources :users. I want to be able to render different versions of the same user. To see if it would work, here's what I tried in my routes.rb:
get "users/:id_alt", :to => "users#alt", :as => :user
and in my controller:
def show
#user = User.find(params[:id])
end
def alt
#user = User.find(params[:id])
end
But when I navigated to users/1, I got this error:
ActiveRecord::RecordNotFound in UsersController#alt
Couldn't find User without an ID
and the error pointed to this line under def alt:
#user = User.find(params[:id])
Anyone know how to remedy this error or accomplish this another way?

It is because you have set your route to use :id_alt
get "users/:id_alt", :to => "users#alt", :as => :user
So the controller is assuming the value in that location should have the name :id_alt not :id. You are not going to be able to have both routes set up this way, but you could do this:
get "users/alt/:id_alt", :to => "users#alt", :as => :alt_user
get "users/:id", :to => "users#show", :as => :user
You will be able to use these path methods: alt_user_path and user_path
And your controller should look like this:
def show
#user = User.find(params[:id])
end
def alt
#user = User.find(params[:id_alt])
render :show
end
Running rake routes will result in this:
alt_user GET /users/alt/:id_alt(.:format) users#alt
user GET /users/:id(.:format) users#show

Related

How to delete / destroy user in rails app from database?

I recently watched the railscast episode #250 Authentication from Scratch (revised) and I have the signup / login / logout actions working. However I am working on creating an action to delete a user from the database, but I am currently experiencing some errors when I try to delete a user.
The users_controller.rb delete / destroy actions look like the following,
def delete
# the below line calls the destroy method / action
self.destroy
end
def destroy
session[:user_id] = nil
# #user = User.find(params[:id])
#user.destroy
# User.find(parmas[:id]).destroy
# the below line didn't delete the current user :(
# #user = User.destroy
redirect_to :controller=>'users', :action => 'new'
end
The error message I'm getting in the browser when I try to delete a user looks like the following.
The page that contains the delete link looks like the following, index.html.erb
<h1>Welcome
<% if current_user %>
<%= current_user.email %>
<% end %>
</h1>
<p>You have <%= current_user.credit %> credits.</p>
<!-- http://stackoverflow.com/questions/5607155/ -->
<%= link_to('Delete your account', :controller => 'users', :action => 'destroy') %>
routes.rb
Rails.application.routes.draw do
# the below generated route is not necessary
# get 'sessions/new'
# delete user route
#get 'delete' => 'users#delete'
# shortened routes, per railscast comment
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
get 'logout' => 'sessions#destroy'
# get 'signup', to: 'users#new', :as 'signup'
# get 'login', to: 'sessions#new', :as 'login'
# get 'logout', to: 'sessions#destroy', :as 'logout'
resources :users
resources :sessions
root to: 'users#new'
# get 'users/new'
# the below line specifies JSON as the default API format
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :users
end
end
It stands to reason you're getting a NoMethodError, since you've never set the #user variable, that line is commented out:
def destroy
session[:user_id] = nil
# #user = User.find(params[:id]) <-- Commenting out this line was your problem
#user.destroy
Changing to
def destroy
session[:user_id] = nil
#user = User.find(params[:id])
#user.destroy
You should be good to go.
EDIT: one thing you'd probably want to do is change from using the old style of link_to, specifying the controller and action, and change to the new style, using route helpers. In this case, you'd use, i believe, link_to 'Delete your account', current_user, :method => :delete, but you can check by running rake routes, where it will list the helpers available based on your routes.rb file.
Well, I think you should make things a bit simpler and start from the dummiest thing, that works. First of all, if you use your controller as a resource, there would not be a delete action there, only destroy.
def destroy
User.find(params[:id]).destroy
session[:user_id] = nil
redirect_to new_user_path
end
P.S. once again, I assume that you have set resources :users in your routes.rb.
If you have a bunch of get|post|put|delete routes instead, just make sure you point the redirect correctly.

`Couldn't find User without an ID` with Friendly_ID gem

I am creating User Profiles with vanity URLs that use the username. The actual profile page works well, however I have my root page as the profile page if the user is signed in. If they are redirected to root then they get the error Couldn't find User without an ID and shows this code as the error pointing to the #user line...
class ProfilesController < ApplicationController
def show
#current_user = current_user
#user = User.friendly.find(params[:id])
#username = "#" + #user.username
#posting = Posting.new
end
end
Here is my routes file as well...
devise_for :users
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
get "profiles/show"
devise_scope :user do
get '/register', to: 'devise/registrations#new', as: :register
get '/login', to: 'devise/sessions#new', as: :login
get '/logout', to: 'devise/sessions#destroy', as: :logout
get '/edit', to: 'devise/registrations#edit', as: :edit
end
authenticated :user do
devise_scope :user do
root to: "profiles#show", :as => "authenticated"
end
end
unauthenticated do
devise_scope :user do
root to: "devise/sessions#new", :as => "unauthenticated"
end
end
get '/:id' => 'profiles#show', as: :profile
This is not the problem with friendly id gem. The problem is that you are redirecting to a show method without supplying id, hence params[:id] is nil.
You can go around this by changing your show method:
def show
#current_user = current_user # why do you need this?
#user = params[:id] ? User.friendly.find(params[:id]) : current_user
#username = "#" + #user.username
#posting = Posting.new
end

undefined method `user_url' for #<UsersController:0x007fda4c2c5208>

Im getting this error after I submit the form.
undefined method `user_url' for #
I am not using the resources :users in my route file and i guess thats why i get the error.
My routes.rb
TaskManager::Application.routes.draw do
get "welcome/index"
root 'welcome#index'
get 'users/new' => 'users#new'
post 'users/' => 'users#create'
post 'users/:first_name' => 'users#show'
end
and my users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
#user.save
if #user.save
redirect_to #user
else
end
end
def show
#user = User.find(params[:first_name])
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email)
end
end
From your code, I'm guessing that the route you want is the post 'users/' => 'users#create'. To Achieve that, I'll you should need to do is change that line to post 'users/' => 'users#create', :as => 'user'.
For future reference: http://guides.rubyonrails.org/routing.html

Rake routes 'match' mapping to the wrong action

My question has to do with mapping to controllers/actions using named routes. I am trying to map '/profile' to 'customers#show'. My routes file looks like this:
root :to => 'pages#home'
## named routes
match "profile" => "customers#show", :as => 'profile'
match 'signin' => 'sessions#new', :as => 'signin'
match 'signout' => 'sessions#destroy', :as => 'signout'
resources :customers do
member do
get 'add_card'
post 'submit_card'
end
end
resources :payments, :only => [:show, :new]
delete 'payments/delete_recurring_payment'
post 'payments/submit_non_recurring'
post 'payments/submit_recurring'
resources :sessions, :only => [:create, :destroy, :new]
Running 'rake routes' gives me this:
root / pages#home
profile /profile(.:format) customers#show
signin /signin(.:format) sessions#new
signout /signout(.:format) sessions#destroy
add_card_customer GET /customers/:id/add_card(.:format) customers#add_card
submit_card_customer POST /customers/:id/submit_card(.:format) customers#submit_card
customers GET /customers(.:format) customers#index
POST /customers(.:format) customers#create
new_customer GET /customers/new(.:format) customers#new
edit_customer GET /customers/:id/edit(.:format) customers#edit
customer GET /customers/:id(.:format) customers#show
PUT /customers/:id(.:format) customers#update
DELETE /customers/:id(.:format) customers#destroy
new_payment GET /payments/new(.:format) payments#new
payment GET /payments/:id(.:format) payments#show
Here is where I'm stumped. When I go to localhost:3000/profile I get a routing error saying this:
No route matches {:action=>"edit", :controller=>"customers"}
This seems odd because there is indeed a route to 'customers#edit' due to my declaring customers as a resource.
However, when I go to 'localhost:3000/signin' I get routed to 'customers#show' which is where I want '/profile' to route to.
It seems like my routes are 'one off' in my routes file but I have no idea why. Any help would be much appreciated.
Thanks
UPDATE 1: Adding my Customers Controller
class CustomersController < ApplicationController
layout "payments_layout"
def show
#customer = current_user
get_account_info(#customer)
get_payment_history(#customer, 10)
end
def new
#title = 'Create an account'
#customer = Customer.new
end
def edit
#customer = current_user
get_account_info(#customer)
end
def update
#customer = current_user
if #customer.update(params[:customer])
redirect_to #customer
else
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
get_account_info(#customer)
render 'edit'
end
end
def create
#customer = Customer.new(params[:customer])
if #customer.save_and_get_stripe_id
sign_in(#customer)
redirect_to #customer
else
#title = 'Create an account'
render 'new'
end
end
def add_card
#customer = current_user
get_account_info(#customer)
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
end
def submit_card
#customer = current_user
res = #customer.add_or_update_card(params)
if res
redirect_to #customer
else
#error = res
customer.get_account_info(#customer)
render 'add_card'
end
end
end
Check your views.
Do you have a link to edit your user profile?
It seems like you actually route to the right controller and action but have some links that rake can't route, e.g. you don't pass the ID to your edit_customer_path link.

No route matches {:action=>“show”, :controller=>“users”}

i following happens, this is my Usercontroller
class UserController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to user_session_path
else
redirect_to new_user_session_path
end
end
def show
#user = User.find(params[:id])
#redirect_to #user
end
end
in my routes.rb I have the following:
Estaciones::Application.routes.draw do
root :to => "static_pages#home"
match '/contact', :to=>'static_pages#contact'
match '/about', :to=>'static_pages#about'
devise_for :user
resources :user do
#resources :car
end
When I run it on my browser I get this:
Routing Error
No route matches {:action=>"show", :controller=>"user"}
Try running rake routes for more information on available routes.
I don't know why this happens???
You need to pass the User object or at least the user id to the link_to method where you're creating the link that you're clicking. Try something like <%= link_to user.name, user %>
Also make sure that your controller is properly named e.g. UsersController (plural).
Rename both the file:
'user_controller.rb' => 'users_controller.rb'
and the constant at the top:
UserController => UsersController
File names must match constants, and the convention is for models to be singular, and controllers to be plural (matching the table).
and try visiting
/users/1

Resources