Avatar image active storage Rails 6 - ruby-on-rails

I'm trying to setup active storage to upload an avatar when a new user register.
I have run:
rails active_storage:install
rails db:migrate
It's a simple app without devise.
I have put "has_one_attached" in model/user.rb
class User < ApplicationRecord
before_save { self.username = username.downcase }
has_one_attached :avatar
end
I have put ":avatar" in strong parameters on user controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#user.avatar.attach(params[:avatar])
if #user.update(user_params)
flash[:notice] = "Your account information was succesfully updated"
redirect_to user_path
else
render 'edit'
end
end
def create
#user = User.new(user_params)
#user.avatar.attach(params[:avatar])
if #user.save
flash[:notice] = "Welcome to Edx Wallet"
redirect_to user_path(#user)
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:username, :avatar)
end
Finally I have put the following code in my navigation view to use a generic avatar in case no user is logged in
<%= image_tag user_avatar(current_user, 40), class: "lg:ml-4 mt-1 lg:mb-0 mb-1 ml-5 pointer-cursor hover:bg-gray-50"%>
And in my application_helper:
def user_avatar(user, size=40)
if user.avatar.attached?
user.avatar.variant(resize: "#{size}x#{size}!")
else
'https://randomuser.me/api/portraits/women/49.jpg'
end
end
But when trying to display Im getting an error:
Showing
/home/edxco/Documents/Microverse/financial_app/app/views/layouts/_nav.html.erb
where line #48 raised:
undefined method `avatar' for nil:NilClass
> def user_avatar(user, size=40)
> if user.avatar.attached?
> user.avatar.variant(resize: "#{size}x#{size}!")
> else
> 'https://randomuser.me/api/portraits/women/49.jpg'
> end
> end
What I am doing wrong? Could you help me, please?

Your user isn't defined. In your helper method try the instance variable #user that you've set in your controller instead of user.

Related

ActiveModel::ForbiddenAttributesError in UserController#register

Im trying to register users on my rails site. When I click the register button on the register page this is what shows up:
ActiveModel::ForbiddenAttributesError in UserController#register
ActiveModel::ForbiddenAttributesError
Here is the code for my user_controller.rb file:
class UserController < ApplicationController
def index
#title = "RailsSpace User Hub"
end
def register
#title = "Register"
if request.post? and params[:user]
#user = User.new(params[:user])
end
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
end
end
end
It's complaining about line 11: #user = User.new(params[:user]) Im following code from a book so I dont know what's wrong with it.
Does anyone have any suggestions? Thanks for all your help in advance.
You should use strong parameters.
The UserController should look like this:
class UserController < ApplicationController
def index
#title = "RailsSpace User Hub"
end
def register
#title = "Register"
if request.post? and params[:user]
#user = User.new(user_params)
end
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
end
end
private
def user_params
# Add the user attributes that you sent with post (form) to the permit method.
params.require(:user).permit(:name, :screen_name)
end
end

NoMethodError (undefined method `search=' for #<Profile:0x000000016d1fb8>) in production mode but not in development mode

My web app works perfectly in development mode but in production mode i cant even log in. Once i log in there is an error which is:
NoMethodError (undefined method `search=' for #<Profile:0x000000016d1fb8>).
The same error appears if i sign up and then create my profile. How do I solve this? I am working with ruby on rails in aws cloud 9 environment and am trying to deploy to heroku. I am using sqllite3 for development and postgressql for production.
this is my profilescontroller.rb
class ProfilesController < ApplicationController
before_action :authenticate_user!
before_action :only_current_user
# GET to /users/:user_id/profile/new
def new
# Render blank profile details form
#profile = Profile.new
end
# POST to /users/:user_id/profile
def create
# Ensure that we have the user who is filling out form
#user = User.find( params[:user_id] )
# Create profile linked to this specific user
#profile = #user.build_profile( profile_params )
if #profile.save
flash[:success] = "Profile Created"
redirect_to user_path(id: 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 their profile page
redirect_to root_path
else
render action: :edit
end
end
private
def profile_params
params.require(:profile).permit(:first_name, :last_name, :avatar, :age, :gender, :city, :collegeemail, :minimumage, :maximumage, :genderpreference, :collegepreference, :search)
end
def only_current_user
#user = User.find( params[:user_id] )
redirect_to(root_url) unless #user == current_user
end
end
It sounds like the table for the Profile model is not the same in production as in development. Specifically, it seems that the search column is missing, causing Profile not to have a getter and setter for search.
I assume you have forgotten to run a migration in production, which adds the search column to the table of the Profile model.
Above error comes whenever we dont have the specific column present in the table. Make sure we have run the migration on the production or just have a look in to schema.rb file and look for column "search" in profile table.

Rails how to require the current password to allow user update

I am having a rather difficult problem i want to update the user profile only if they submit the current password.I am not using devise.And another post here at stack overflow didn't really help me.
This is my User controller code:
class UsersController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
#user_posts = #user.posts if #user
if #user
if #user_posts
render 'show.html'
else
render 'show.html'
end
else
render file: 'public/404.html', status: 404, formats: [:html]
end
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to root_path
flash[:notice] = "Successfully Signed up :-)"
else
redirect_to signup_path
flash[:notice] = "You didn't sign up successfully :-("
end
end
def edit
#user = User.find(params[:id])
if current_user.id = #user.id
render 'edit'
else
redirect_to #user
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:notice] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
:password == :password_confirmation
private
def user_params
params.require(:user).permit(:user_name, :email, :password, :password_confirmation)
end
end
And this is my user.rb:
class User
has_secure_password
has_many :posts
has_many :comments
def admin?
self.role == 'admin'
end
def moderator?
self.role == 'moderator'
end
end
Please help because I have been working with this for a long time now. And the other solution about this topic here at stack overflow didn't work.
One way is to use virtual attributes
1. The User model
class User < ActiveRecord::Base
attr_accessor :current_password
end
2. The form
add the current_password attribute to the form as a text_field input
3. The UsersController
def update
#user = User.find params[:id]
if #user.authenticate(update_params[:current_password])
# update the user
# maybe check if the data are valid
#user.update(update_params)
else
flash[:warning] = "Please provide your password"
#user.errors.add :current_password, "invalid"
render :edit
end
end
def update_params
params.require(:user).permit(:current_password, :email)
end
First, you have a problem in your edit action:
current_user.id = #user.id
That assigns #user.id to current_user.id - you wanted == to test that it's the correct User. You should put a similar check on update, and probably extract it into a before_action so you can easily apply it anywhere you want to.
To check that the password is present, add it to your form like any other field and then get it out of params to verify it. That would look something like this:
class UsersController < ApplicationController
def update
encrypted = encrypt(params[:password]) # Using whatever your mechanism is
if encrypted == #user.encrypted_password
# Update the user
else
flash[:notice] = 'Password is required to update user information.'
redirect_to edit_user(path(#user))
end
end
end

No Method Error

I am getting a NoMethodError in Users#show undefined method 'name' for nil:NilClass on the following code.
Show view:
<% provide(:title, #user.name) %>
<div class="row">
...
Users controller:
class UsersController < ApplicationController
def new
#user = User.new
render :layout => false
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to the BluePlaque Explorer!"
redirect_to #user
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password,
:password_confirmation)
end
def login
render :layout => false
end
end
The show view what displays user's profile page after successful registration. Cannot see what causes it.
NoMethodError in Users#show undefined method 'name' for nil:NilClass
Apart from the apparent fact you don't have a .name method for your User model, there is another problem highlighted by this error... that your #user variable is not set.
Rails/Ruby doesn't handle "undeclared" variables in the expected way; it assigns them to nil:NilClass - it messes up developer's minds because they think the method is the error, when really, it's the lack of #object to call the method on.
The bottom line is that you need the following:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find params[:id]
end
end
This will set your #user variable, with which you'll be able to call .name or whatever:
#app/views/users/show.html.erb
<%= #user.first_name %>
--
Now... a cool trick for you:
#app/models/user.rb
class User < ActiveRecord::Base
def name
first_name + " " + last_name
end
end
This will allow you to call #user.name if #user is set!
You always have able to use try if not sure about presense
<% provide(:title, #user.try(:name)) %>

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.

Resources