Trouble Creating and showing Users in Rails blog - ruby-on-rails

I keep getting a variety of error while trying to create and show errors in a simple Rails blog I'm trying to create.Let me know if you see anything obvious or if you need me to post more code as I've tried a number of things but to no avail. Thanks
The browser is giving me this error
Couldn't find User without an ID
in my "logged_in?" method which shows
def logged_in?
#current_user ||= User.find(session[:user_id])
end
Sessions Controller
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
flash[:success] = "You are logged in"
redirect_to root_path
else
render action: 'new'
flash[:error] = "There was a problem logging in. Please check your email and password"
end
end
end
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
def edit
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
flash[:notice] = "You have registered, please login"
redirect_to login_path
else
render :new
end
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
end
Articles Controller
class ArticlesController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def new
#article = Article.new
end
def index
#article = Article.all
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def show
#article = Article.find(params[:id])
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :image)
end
end
Application Helper
module ApplicationHelper
def logged_in?
#current_user ||= User.find(session[:user_id])
end
end

The problem you're facing is that session[:user_id] is nil. Usually a method which sets current user is called current_user. The logged_in? is not a good name for a method setting an user instance, because one would expect that a method ending with a question mark would return a true or false. And not an user instance.
Also, setting the current user is usually done with a before_filter. Additionally, you want to skip such before filter for action where you're setting the current user (i.e the current_user doesn't exist yet)
Finally, I would rather fail gracefully, if user is not found. You can achieve this by changing your code to User.find_by_id(session[:user_id])

While the user is not loggued, session[:user_id] is nil, and so User.find(session[:user_id]) generates the error. The method should be like this:
def logged_in?
#current_user ||= User.find(session[:user_id]) if session[:user_id].present?
end

Why would the logged_in? helper method try to assign a value to #current_user? I think that is a bad logic, it should just return a boolean result without modifying such a central instance. This is a proper way to do that:
def logged_in?
#current_user.nil? ? false : true
end
The responsibility of setting the #current_user falls to a method that you should place in application_controller.rb and make it a before_action so that it's executed before any controller action is triggered, that is:
# app/controllers/applicaton_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
before_action :authenticate_user
# Your actions here
..
..
#
private
def authenticate_user
#current_user ||= User.find(session[:user_id]) if session[:user_id].present?
end
end

Related

App not creating sessions and #current_user not working

I have some code here that is supposed to create a session upon login, and create "#current_user". However, neither of these things are working, and after 2 days of speculating, I can't figure out why.
Users controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to login_path
flash[:success] = "Account created. You may now log in"
else
redirect_to '/signup'
flash[:warning] = "Something went wrong. Try again."
end
end
private
def user_params
params.require(:user).permit(:username, :jabber_id, :password)
end
end
Sessions controller:
class SessionsController < ApplicationController
def new
end
def create
#user = User.find_by_username(params[:session][:name])
if #user && #user.authenticate(params[:session][:password])
session[:user_id] = #user.id
redirect_to '/posts'
else
session[:user_id] = nil
flash[:warning] = "Failed login- try again"
redirect_to '/login'
end
end
def destroy
session[:session_id] = nil
redirect_to login_path
end
end
Application controller:
class ApplicationController < ActionController::Base
def current_user
return unless session[:user_id]
#current_user ||= User.find(session[:user_id])
end
def require_user
redirect_to '/login' unless current_user
end
end

rails user_id add to a picture

I let users to upload photos using paperclip, but there is no ownership in the photo. Which means, I don't know who uploaded the photos at all.
Here, I would like when someone uploads a picture you know which user uploaded it. i have a user_id column. but i dont know how to implement the code in the pic controller
How do I do that? Thanks!
class PicsController < ApplicationController
before_action :find_pic, only: [:show, :edit, :update, :destroy]
def index
#user = User.find( params[:user_id])
#pics = Pic.all.order("created_at DESC")
end
def show
end
def new
#pic = Pic.new
end
def create
#pic.user = current_user
#pic = Pic.new(pic_params)
if #pic.save
redirect_to #pic, notice: "Yes it was posted"
else
render 'new'
end
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile
end
def update
if #pic.update(pic_params)
redirect_to #pic, notice: "Congrates Pic was upaded"
else
render 'new'
end
end
def destroy
#pic.destroy
redirect_to users_path
end
private
def pic_params
params.require(:pic).permit(:title, :description, :profile_id)
end
def find_pic
#pic = Pic.find(params[:id])
end
end
class UsersController < ApplicationController
before_action :authenticate_user!
def index
#pics = Pic.all.order("created_at DESC")
end
def show
#user = User.find(params[:id])
#pics = User.find_by(user_name: params[:user_name])
end
end
class ProfilesController < ApplicationController
before_action :authenticate_user!
before_action :only_current_user
def new
#user = User.find( params[:user_id])
#profile = Profile.new
end
def create
#user = User.find(params[:user_id])
#profile = #user.build_profile(profile_params)
if #profile.save
redirect_to user_path( params[:user_id])
else
render action: :new
end
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile
end
def update
#user = User.find(params[:user_id])
#profile = #user.profile
if #profile.update_attributes(profile_params)
flash[:success] = "Profile Updated"
redirect_to user_path(params[:user_id])
else
render action: :edit
end
end
private
def profile_params
params.require(:profile).permit(:avatar, :user_name, :contact_email, :description)
end
def only_current_user
#user = User.find(params[:user_id])
redirect_to(root_url) unless #user == current_user
end
end
If the user can be identified during the upload process, you can try to pass the user_id in a hidden_field during upload. You said you already created the user_id column.
<%= f.hidden_field :user_id , value: #user.id %>
for this code to work you need to find the #user in your controller action. Similar to what you are doing already in your 'index' action: find user by the :user_id
If you are using devise for User you can use current_user.id instead.

User can't be blank on Rails

Hello I am learning rails and I have made a mistake that error message shows when I submit the article but can't seem to know where the problem is. I think it's a controller?
Github files of my code:
GitHub Project
users_controller.rb
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "welcome to the alpha blog #{#user.username}"
redirect_to articles_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
flash[:success] = "Your account was updated successfully"
redirect_to articles_path
else
render 'edit'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
end
articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
# Helppppp!
def index
#articles = Article.all
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
#article.user = User.new
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render :new
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was successfully updated."
redirect_to article_path(#article)
else
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was successfully deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
end
Look at your method:
def create
#article = Article.new(article_params)
#article.user = User.new
...
end
You are trying to assign empty user to your article object. You should pass user_id as a param (don't forget to add it as a permitted param in article_params) and your code should be:
#article.user = User.find(article_params[:user_id])
Fixed it by defining current_user method in the application_controller.rb and added the following:
**application_controller.rb**
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def logged_in?
!!current_user
end
def require_user
if !logged_in?
flash[:danger] = "You must be logged in to perform that action"
redirect_to root_path
end
end
end
articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
before_action :require_user, except: [:index, :show]
before_action :require_same_user, only: [:edit, :update, :destroy]
def index
#articles = Article.paginate(page: params[:page], per_page: 5)
end
def new
#article = Article.new
end
def edit
end
def create
#article = Article.new(article_params)
#article.user = current_user #code that needs fix
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render :new
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was successfully updated."
redirect_to article_path(#article)
else
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was successfully deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
def require_same_user
if current_user != #article.user
flash[:danger] = "You can only edit or delete your own article"
redirect_to root_path
end
end
end

RoR - NoMethodError, undefined method

I have created an app with simple login authentication, it is actually a twitter clone. The user logs in and access the pages, etc.
But when the user posts something from there profile. It gives an error
NoMethodError in RibbitsController#create
undefined method `id=' for nil:NilClass
The error is around line 5:
class RibbitsController < ApplicationController
def create
#ribbit = Ribbit.create(user_ribbits)
#ribbit.userid = current_user.id
if #ribbit.save
redirect_to current_user
else
flash[:error] = "Problem!"
redirect_to current_user
end
end
private
def user_ribbits
params.require(:ribbit).permit(:content, :userid)
end
end
The request given to app:
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"dwVmjDNO4GOowphGFgChMDBxBfvka+M/xSUHvJMECzwxtv4NF6OuWtiaX74NLz91OwQJ9T9+wm7yMiPQ0BLpGA==",
"ribbit"=>{"content"=>"hi. test.\r\n"},
"commit"=>"Ribbit!"}
The sessions controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_username(params[:username])
if user && user.authenticate(params[:password])
session[:userid] = user.id
redirect_to rooturl, notice: "Logged in!"
else
flash[:error] = "Wrong Username or Password."
redirect_to root_url
end
end
def destroy
session[:userid] = nil
redirect_to root_url, notice: "Logged out."
end
end
The users controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.create(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to #user, notice: "Thank you for signing up!"
else
render 'new'
end
end
def show
#user = User.find(params[:id])
#ribbit = Ribbit.new
end
private
def user_params
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation, :avatar_url)
end
end
And the application controller
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
I would really appreciate it if you guys would help!
Thanks.
You're trying to assign current_user.idto #ribbit.userid without ensuring that current_user is set. 'current_user' would be set only if a user has been previously saved before.
Therefore, you need either to make sure that an authenticated user is trying to create a Ribbit, or if you consider the userid as a non mandatory field, you can simply change your line 5 by:
#ribbit.userid = current_user.id unless current_user.blank?
If you only want authenticated user to create Ribbits, then consider using a gem to handle authentication such as Devise. You could then use before_filter :authenticate_user! in your controller to make sure users are properly authenticated.

declerative_authorization on User problem

I am trying to block all default methods except create and update in my users controller using declerative_authorization. But at the time I add filter_resource_access or filter_access_to into my usersController i always get "Couldn't find User without an ID". Anyone care to explain why this could be happening?
class UsersController < ApplicationController
filter_resource_access
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Account registered!"
redirect_to account_url
else
render :action => :new
end
end
def show
#user = #current_user
end
def edit
#user = #current_user
end
def update
#user = #current_user # makes our views "cleaner" and more consistent
if #user.update_attributes(params[:user])
flash[:notice] = "Account updated!"
redirect_to account_url
else
render :action => :edit
end
end
end
You should set the #user variable before the filter_access_to call with a before_filter as declarative_authorization tries to access #user when you call filter_access_to.
before_filter :set_user
filter_access_to :all
...
protected
def set_user
#user = #current_user
end
Maybe you are setting the attribute_check parameter to true in your filter_access_to call? I have a similar controller and I don't really need the before_filter.
Another thing that might be causing it is a using_access_control call in your User model.

Resources