Railscast Login Remember me - ruby-on-rails

i followed the revised railcast and then decided to upgrade my code with a remember feature. Almost work but When going to the login page I get the following error
Couldn't find Customer with auth_token =
Note I change the table from User to Customer
Here my code, maybe i made a little mistake. I did a reset on the database
Customer Controller
class CustomersController < ApplicationController
def new
#customer = Customer.new
end
def create
#customer = Customer.new(params[:customer])
if #customer.save
session[:customer_id] = #customer.id
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
end
Session Controller
class SessionsController < ApplicationController
def new
end
def create
customer = Customer.find_by_email(params[:email])
if customer && customer.authenticate(params[:password])
if params[:remember_me]
cookies.permanent[:auth_token] = customer.auth_token
else
cookies[:auth_token] = customer.auth_token
end
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
cookies.delete(:auth_token)
redirect_to root_url, :notice => "Logged out!"
end
end
Route.rb
get 'signup', to: 'customers#new', as: 'signup'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
resources :sessions
resources :customers
root :to => 'sessions#new'
Application Controller
class ApplicationController < ActionController::Base
protect_from_forgery
private
def authorize
redirect_to login_url, alert: "Not authorized" if current_customer.nil?
end
def current_customer
#current_customer ||= Customer.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
helper_method :current_customer
end
Thanks everyone

My mistake was in the following code
def current_customer
#current_customer ||= Customer.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
and fixing it by the following
def current_customer
#current_customer ||= Customer.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
end

Related

Ruby on rails "Could find user with id= create"

i don't know what's wrong, I tried to add "create" method to my application, and what i get is :
"ActiveRecord::RecordNotFound in UsersController#show"
"Couldn't find User with id=create"
And then code
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
here's my User controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def create
#user = User.new(user_params)
respond_to do |user|
if #user.save(user_params)
user.html { redirect_to users_path, :notice => "User has been created!" }
else
user.html { redirect_to create_user_path(#user), :notice => "Sorry, couldn't create user. Try again!" }
end
end
end
def edit
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_path, :notice => "User has been updated!" }
else
format.html { redirect_to edit_user_path(#user), :notice => "Sorry, couldn't update user. Try again!" }
end
end
end
def destroy
#user.destroy
respond_to do |d|
d.html { redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
end
private
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
def user_params
params.require(:user).permit(:name, :email)
end
end
The thing is, the index page works perfectly fine, but if i try to go somewhere else, like /users/create i get that error.. I tried changing routes, rewriting the code, nothing helps.My routes are like this:
# Root '/'
root "users#index"
# Show Users
get "users/:id" => "users#show"
Can you guys help me ? I am literally stuck, as to how fix that problem :c
This should help you - you're missing resources :users, which creates a set of RESTful routes for your controller. This, combined with the other answers should help
You don't go to the create action via a URL. It's there to create a new user coming back from the new.html.erb file.
If you want to create a new user you could use /users/new and add a new method to your controller along the lines of:
def new
#user = User.new
end
You will also need to change your routes.rb file to add all the default actions like:
resources :users
I suggest you work through http://guides.rubyonrails.org/getting_started.html.
In your controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path, :notice => "User has been created!"
else
render :new
end
end
def edit
end
def update
if #user.update(user_params)
redirect_to users_path, :notice => "User has been updated!"
else
render :edit
end
end
def destroy
#user.destroy
redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email)
end
end
You are using all RESTful actions, so you can add to routes.rb:
resources :users
And remove this:
get "users/:id" => "users#show"

How to pass parameters when building an Object in Rails controller

I have an Event model and a Notifications model. An event has many notifications, and a notification only has one event. My notification object has two attributes: message and event_id. When I build a new notification, how can I set the event_id to the current event's id?
events_controller.rb
class EventsController < ApplicationController
before_action :signed_in, only: [:new,:create]
def new
#event = Event.new
end
def create
#event = Event.new(event_params)
if #event.save
flash[:success] = "Your Event has been created."
redirect_to root_path
else
render 'new'
end
end
def show
#event = Event.find(params[:id])
#notification = #event.notifications.build
respond_to do |format|
format.html
format.xml { render :xml => #event }
format.json { render :json => #event }
end
end
private
def event_params
params.require(:event).permit(:name, :description)
end
def signed_in
unless user_signed_in?
redirect_to new_user_session_path
flash[:warning] = "You must be signed in to access that page"
end
end
end
notifications_controller.rb
class NotificationsController < ApplicationController
def create
#notification = Notification.new(notification_params)
if #notification.save
redirect_to root_path
flash[:success] = "Your message has been sent"
else
render 'new'
end
end
def show
end
private
def notification_params
params.require(:notification).permit(:message, :event_id)
end
def signed_in
unless user_signed_in?
redirect_to new_user_session_path
flash[:warning] = "You must be signed in to access that page"
end
end
end
routes.rb
devise_for :users
resources :events
resources :notifications
root 'static_pages#home'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
#notification = #event.build_notification(notification_params)

Advanced contraints in rails 3 for user-centric routing

Learning rails development and would usually prefer to search out an answer than waste peoples time but this has been doing my head in all night.
Essentially I'm trying to present user-dependant views ala github etc.
I'm trying to follow the instructions laid out here:
http://collectiveidea.com/blog/archives/2011/05/31/user-centric-routing-in-rails-3/
My authentication at the moment is from the railscast "Authentication from Scratch - revised" which uses sessions, my sessions_crontroller.rb:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
end
And my routes.rb:
C::Application.routes.draw do
root :to => "static_pages#home", :constraints => LoggedInConstraint.new(false)
root :to => "users#show", :constraints => LoggedInConstraint.new(true)
resources :users
resources :sessions
As per my understanding, because I'm not using cookies the final comment under that blog posts recommends using request.session[:your_key] in place of request.cookies.key?("user_token") however when logged in I am still taken to static_pages#home? If anyone could shed some light on the topic I would very much appreciate it.
I also apologise for any formatting errors etc, this is my first question on stackoverflow.
Thanks again!
Not sure about your exact question, but I just did something kind of similar to this, so maybe my code will help you:
My routes:
# Except from config/routes.rb
require File.expand_path("../../lib/role_constraint", __FILE__)
MyApp::Application.routes.draw do
mount Resque::Server, :at => "/resque", :constraints => RoleConstraint.new('admin')
...
...
...
My constraint:
# lib/role_constraints.rb
class RoleConstraint < Struct.new(:value)
def matches?(request)
request.session[:role] == value
end
end
My sessions controller:
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
before_filter :require_user, :only => :destroy
def new
end
def create
user = User.find_by_username(params[:username])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
# Just for /resque
# Not secure - if you change a user's role, it will not be updated here
# until they log out and log in again.
session[:role] = user.role
if user.email.nil?
redirect_to user, :notice => "Please add your email address to your account"
else
redirect_to root_url, :notice => "Logged in!"
end
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
session[:current_project_id] = nil
redirect_to root_url, :notice => "Logged out!"
end
end

RailsTutorial Sessions: Sign In doesn't flash success and sign out causes routing error

Following Hartl's railtutorial. When I try to log in, it takes me to the correct page, but "Successful login!" does not flash on the interface. Also, when I try to sign out, I get a Routing Error: No route matches [GET] "/sessions/1".
Any help would be appreciated!
Here is my sessions_controller.rb:
class SessionsController < ApplicationController
def new
#title = "Log in"
end
def create
user = User.authenticate(params[:session][:email],
params[:session [:password])
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = "Sign in"
render 'new'
else
flash[:success] = "Successful login!"
sign_in user
redirect_back_or user
end
end
def destroy
sign_out
redirect_to root_path
end
end
Here is my routes.rb:
SampleApp::Application.routes.draw do
#resources :users this is the line I removed to get my code to work
resource :user #this is the lined I added to get my code to work
resources :sessions, :only => [:new, :create, :destroy]
match '/sessions', :to => 'users#show'
match '/signup', :to => 'users#new'
match '/login', :to => 'sessions#new'
match '/logout', :to => 'sessions#destroy'
root :to => 'pages#home'
Changing resources :users to resource :user seems to allow me to "sign in" and "sign out" except that the flash success still does not appear on the user interface. This leads me to believe that there is an error in my create method.
Here is my sessions_helper.rb:
module SessionsHelper
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
def signed_in?
!current_user.nil?
end
def current_user=(user)
#current_user = user
end
def current_user
#current_user ||= user_from_remember_token
end
def current_user?(user)
user == current_user
end
def sign_out
cookies.delete(:remember_token)
self.current_user = nil
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
private
def user_from_remember_token
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
def store_location
session[:return_to] = request.fullpath
end
def clear_return_to
session[:return_to] = nil
end
end
Edited: Solution posted in code.
i think you should user just flash[:success] and flash[:error] and not the flash.now
and what link are you using for loging out?

Nesting resource

I'm trying to nest my messages controller into my channels controller. But when I go to my messages view i get the error "couldn't find channel with no id"
class MessagesController < ApplicationController
def index
#channel = Channel.find(params[:channel_id])
#messages = #channel.messages
end
def new
#channel = Channel.find(params[:channel_id])
#message = #channel.messages.build
end
def create
#channel = Channel.find(params[:channel_id])
#message = #channel.messages.build(params[:message])
if #message.save
flash[:notice] = "Successfully created message."
redirect_to channel_url(#message.channel_id)
else
render :action => 'new'
end
end
def edit
#message = Message.find(params[:id])
end
def update
#message = Message.find(params[:id])
if #message.update_attributes(params[:message])
flash[:notice] = "Successfully updated message."
redirect_to channel_url(#message.channel_id)
else
render :action => 'edit'
end
end
def destroy
#message = Message.find(params[:id])
#message.destroy
flash[:notice] = "Successfully destroyed message."
redirect_to channel_url(#message.channel_id)
end
end
Channels controller
class ChannelsController < ApplicationController
def index
#channels = Channel.find(:all)
end
def show
#channel = Channel.find(params[:id])
#message = Message.new(:channel => #channel)
end
def new
#channel = Channel.new
end
def create
#channel = Channel.new(params[:channel])
if #channel.save
flash[:notice] = "Successfully created channel."
redirect_to #channel
else
render :action => 'new'
end
end
def edit
#channel = Channel.find(params[:id])
end
def update
#channel = Channel.find(params[:id])
if #channel.update_attributes(params[:channel])
flash[:notice] = "Successfully updated channel."
redirect_to #channel
else
render :action => 'edit'
end
end
def destroy
#channel = Channel.find(params[:id])
#channel.destroy
flash[:notice] = "Successfully destroyed channel."
redirect_to channels_url
end
end
routes.rb
SeniorProject::Application.routes.draw do
resources :users
resources :channels, :shallow => true do |channels|
channels.resources :messages
end
root :channels
resources :users, :user_sessions
match 'login' => 'user_sessions#new', :as => :login
match 'logout' => 'user_sessions#destroy', :as => :logout
match ':controller(/:action(/:id(.:format)))'
end
What's going on here is that this line:
#channel = Channel.find(params[:channel_id])
Is falling over because there's no defined channel_id in the params hash. I see you're using shallow routes, which means your uri probably looks like this:
/messages
And you need it to look like:
/channels/1/messages
Try changing your url to be:
channel_messages_url(#channel)
instead of
messages_url
This is a guess btw, it could be because of the way you've defined your routes.rb, which looks a little odd because you're defining the messages routes twice, once with the has_many and again as a proper resource. You probably want something like:
# assuming you need shallow routes
resources :channels, :shallow => true do |channels|
channels.resources :messages
end

Resources