Ruby on Rails Accessing params from controller from form - ruby-on-rails

I'm trying to access parameters in my controller as strings
When I log
Rails.logger.debug "!!!" << "#{params[:username]}"
nothing comes after the exclamation points even though
Rails.logger.debug params.inspect
shows that username has a value.
Can someone please tell me how to get the username value to show up in my log debugging statement?
Controller Code:
def create
Rails.logger.debug params.inspect
Rails.logger.debug "!!!" << "#{#user[:username]}"
#user = Users.new(user_params)
{params[:birth_year]}"
if #user.save
redirect_to(:controller => 'users', :action => 'index')
else
render(:controller => 'access', :action => 'index')
end
end
last few lines of logged info:
"user"=>{"username"=>"TrevorTT" ...
!!!

#user would not work in this line Rails.logger.debug "!!!" << "#{#user[:username]}" because it's not created yet. Either move
#user = Users.new(user_params) above logger.
But as per my understanding you just want to log username params only.
So you can do it like this params[:user][:username] because username nested under user params. So your code should be:
def create
Rails.logger.debug params.inspect
Rails.logger.debug "!!!" << "#{params[:user][:username]}"
....
end

#user is called before it is defined. It will return nil.
def create
#...
Rails.logger.debug "!!!" << "#{#user[:username]}" # <-- #user is nil
#user = User.new(user_params)
You can either leave the line in place and use user_params
def create
#...
Rails.logger.debug "!!!" << "#{user_params[:username]}"
#user = User.new(user_params)
or move the line below #user =
def create
#...
#user = User.new(user_params)
Rails.logger.debug "!!!" << "#{#user[:username]}"
Also, your model names should be singluar (eg. User).

Related

Rails session[:user_id] wont destroy

Im new to Rails and having troubles trying to destroy the user session.
My session controller looks like this
class SessionsController < ApplicationController
def new
end
def create
name = params[:name]
password = params[:password]
user = User.authenticate(name, password)
if user.nil?
render json: {isLogin: false}
else
session[:user_id] = user.id
render json: {isLogin: true}
end
end
def destroy
session[:user_id] = nil
puts session[:user_id] # Nothing gets printed to the console here
render json: {isLogin: false}
end
end
When I call 'sessions/destroy' and try to destroy the session, nothing gets printed at 'puts session[:user_id]' line. So I know for sure that the session is nil at that point. But the problem is that I can still access the session like this from a different controller even after I destroy the session for that user.
class LessonsController < ApplicationController
def getLesson
userId = session[:user_id]
# do stuff
end
end
Why is this happening? and how can I fix this?.
Try
session.delete(:user_id)
instead of
session[:user_id] = nil
That is what I have had luck with in the past.

Redirect_to in model after error

I have a function in my model to import data from a CSV file and I'd like to have validations should there be any errors. For example, when I upload the file, I search for a User based on an ID in the file. If there is no User with that ID, I'd like to redirect_to a different page with an error.
def self.getUser(scale_id)
#user = User.find_by(scale_id: scale_id)
if #user == nil
redirect_to users_path
else
return #user
end
end
def self.bulk_upload_weigh_ins(file)
output = []
errors = []
CSV.foreach(file.path, headers: true, ) do |row|
row = row.to_hash
#scale_id = row["scale_id"]
#user = getUser(#scale_id)
row.merge!(user_id: #user_id)
WeighIn.create! row.to_hash
end
end
...and no matter what path I put there, I get the following: undefined local variable or method 'users_path' for #<Class:0x007fa06f466998> even when it is a valid path.
Is there something wrong with redirecting like this? If yes, how should I do it?
The cleanest way for custom validations is to do something like:
In your model:
User < ActiveRecord::Base
validate :get_user
def initialize(params={})
self.id = params[:id]
end
def get_user
#user = User.find_by(self.id)
if #user.nil?
errors.add(:base, "Invalid User")
return false
else
return #user
end
end
In your controller you'd then do:
def whatever_action_youre_using
#user = User.new(user_params)
unless #user.valid?
redirect_to users_path
end
end
def user_params
params.require(:user).permit(:first_name, :email, :etc, :whatever_your_atts)
end
I have a function in my model that is searching for a User based on an
ID
undefined local variable or method 'users_path' for
Class:0x007fa06f466998
As #Dave Newton mentioned in the comments, the path helpers are not available in models unless you specifically include them. Also you can't and never need to use redirect_to in a model. The application logic should be moved to the controller. Something like below should work
def get_user
#user = User.find_by(scale_id: params[:user][:scale_id])
if #user.nil?
redirect_to users_path, notice: 'Your error message here'
else
return #user
end
end

how to identify the method name that calling the particular function?

I want to change the subject of mail according to actions(create, update), that call the mailer. How to do this? (ex. during creation, subject is User created and for update , user updated)
def create
#user = User.new(params[:user])
#user.save
Mailer.notify(#user).deliver
end
def update
#user = User.find(params[:id])
#user.update
Mailer.notify(#user).deliver
end
mailers.rb
def notify(user)
#user =user
mail(:to =>#use.mail :subject => "created")
end
# controller
def create
#user = User.create(params[:user])
Mailer.notify(#user, 'created').deliver
end
def update
#user = User.find(params[:id])
#user.update
Mailer.notify(#user, 'updated').deliver
end
# mailers.rb
def notify(user, action_name)
#user = user
mail(:to => #user.mail, :subject => "User #{action_name}")
end
You can get the name of the calling method by using
caller_locations(1)[0].label
Example:
def bar
caller_locations(1)[0].label
end
def foo
bar
end
foo # => "foo"

Updating a record via a action method

User signs up, is redirected to a page to be collected info, pretty straight forward
I for my life can't figure out how to do this
My controller for the user
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def additional_info
#user = User.find session[:user_id]
#user = User.update(user_addinfo)
redirect_to user_path
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.require(:user).permit(:year)
end
end
user_addinfo is the action method that i want to call updating my record on for my additional_info method.
the def create method has commented line that i'm unsure if necessary, particularly the session[:user_id] = #user.id. I was told that i need this in order to keep track of my session, but perhaps someone can debunk this for me, as im following michael hartl's tutorial.
as of right now with this code, rails is giving me a parameter missing in the
params.require(:user).permit(:year) line.
Much help is greatly appreciated. Ive been trying many different things, and cant seem to figure this out
Change your controller code as below:
def additional_info
#user = User.find params[:id] ## Set #user
end
def update
if #user.update(user_addinfo)
redirect_to user_path(#user), notice: 'User was successfully updated.'
else
render action: 'additional_info'
end
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path(#user) ## Pass #user
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
and in your routes.rb update the additional_info route as
get 'info/:id' => 'users#additional_info', :as => 'additional_info'
You additional_info action seems to be wrong. You need to pass in the id of the user for whom you are collecting additional information.
def additional_info
#user = User.find params[:id]
#user.update_attributes(user_addinfo)
redirect_to user_path(#user)
end
The line you have commented in your create method:
#session[:user_id] = #user.id
Is what is storing the user id to a session variable and not a param in the url.
You then have this line commented in your additional_info method
#user = User.find session[:user_id]
This is looking up the user by the id that you would have previously stored in the session variable.
At that point the user object would be stored in user
If you need it in your instance variable, make sure to modify the line to be
#user = User.find session[:user_id]
Your user would then be stored in #user and be able to be accessed in the view

using redirect and if multiple times

My question is actually fairly simple, how do I make a create action which checks if a user is logged in, and if she/he is then redirect to the dashboard instead of rendering the index page where they've got links and stuff to go to and sign up. Also why is the code below not working.
class UsersController < ApplicationController
def new
#user = User.new
end
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
end
Your code isn't doing what you expect because the if statements are actually nested (you want elsif with this same structure -- or see my suggested fix below). Here's what your code, when properly formatted, actually looks like:
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
Logically, you will never get down into the second if statement, because current_user must be nil to enter the first. Try something like this instead:
def create
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
else
redirect_to dplace_index_path
end
end
I rearranged the code, but it should logically do what you want now. I put the "happy path" first (the current_user exists), and moved the redirect into the else statement.
General user authentication:
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to dashboard_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
Try:
def create
if current_user.blank? # .blank? will check both blank and nil
# logic when user is not logged in
redirect_to index_path
else
# logic when user is logged in
redirect_to dashboard_path
end
end
def create
redirect_to dplace_index_path unless current_user
# no need to check current_user again
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end

Resources