How to define a current_model for a model in rails? - ruby-on-rails

I think my question title is bit confusing. But what I am meaning to ask is I am creating my own authentication system using mobile. Just like devise comes with current_user to create a session, I want to know how can I achieve same on a different model.
I have a model called Commuter. It also has a id with it.
A record of commuter looks like this.
Commuter.last
<Commuter id: 867, phone_number: "9483942090">
I am trying to create a session after verfying the mobile number with my controller method as follows:
def verify
#commuter = Commuter.where(phone_number: params[:phone_number]).first
if (#commuter && #commuter.authenticate_otp(params[:otp],drift:300))
#commuter.auth_active = true
if #commuter.save
#Removed from session after verified it
session[:phone_number] = nil
session[:is_verified] = nil
#signed in commuter after verified it
sign_in(:commuter, #commuter)
flash[:notice] = "Your mobile no is verified."
end
else
flash[:alert] = "You have entered wrong otp.Please check again."
end
puts "#{current_commuter.phone_number}"
redirect_to root_path
end
I just a puts there to debug. So right now I am getting current_commuter as undefined local variable for obvious reasons I guess. So I wanted to know how can achieve this session based current commuter ?

You can save the Commuter id in the session as session[:cid] = 1 and create a method on your base controller like this
def current_commuter
#commuter ||= Commuter.find session[:cid]
end
helper_method :current_commuter

Related

Undefined method for UserMailer:Class

I've got an app where users submit weeks which can be approved or denied, and in my weeks controller I have the following lines meant to iterate over the selected weeks, find their corresponding users and send each user an email:
elsif params[:commit] == "Reject selected weeks"
user_week = Week.where(id: params[:weeks_ids])
user_week.update_all(approved?: false)
# fetch the set of user_emails by converting the user_weeks to user_ids
users = User.find(user_week.pluck(:user_id))
users.each do |user|
#iterate over the users and send each one an email
UserMailer.send_rejection(user).deliver
end
flash[:info] = "Selected weeks were Rejected."
end
redirect_to weeks_path
When I attempt to reject a week, I receive the following error message:
undefined method `send_rejection' for UserMailer:Class
I'm adding on to pre-existing code and have little knowledge of MVC, so the only issues I can think of would be with placing the mailer method in the wrong file or sending an incorrect type of arg to the mailer method.
Here is "send_rejection", the mailer contained in my user model.
def send_rejection(user)
UserMailer.reject_timesheet(user).deliver_now
end
The corresponding method in my user_mailer.rb file:
def reject_timesheet(user)
#greeting = "Hi"
mail to: user.email, subject: "Rejected Timesheet"
end
New to rails and not sure where I'm going wrong.
This is not a problem of MVC, one question I'd probably ask is why are you not calling the reject_timesheet directly instead of send_rejection.
You're getting the error because as you said the method is defined in the user model, so in order to call the method, you'd need to do:
user.send_rejection
In which case I doubt you'd be needing to pass a user argument to the send_rejection, as you could just do:
class User
def send_rejection
UserMailer.reject_timesheet(self).deliver_now
end
end
then in your controller:
...
users.each do |user|
#iterate over the users and send each one an email
user.send_rejection
end
...
I believe you could also clean up your codebase a bit and possibly refactor some logic, but basically this approach should resolve your errors.
Let me know if that helps

What does the 3rd line of code from the below snippet does?

def create
chef = Chef.find_by(email: params[:email])
if chef && chef.authenticate(params[:password])
**session[:chef_id] = chef.id**
flash[:success] = "You logged In"
redirect_to recipes_path
else
flash.now[:danger] = "Check your email or password"
render 'new'
end
end
What does
session[:chef_id] = chef.id
do? Is that session[:chef_id] a kind of variable or something? To which the id of a chef is assigned? Can I use some other name there?
That's storing the chef_id in the session, which is a way of persisting data accross multiple requests. It's not specific to Rails, as the session is also available in all web applications. You could read more on the Rails session here and more on web sessions here
session[:chef_id] = :foo stores chef_id key in session with value of :foo.
So you can fetch assigned :foo value later by calling session[:chef_id].
In your code it is assigned to id of chef who has email equals to params[:email].
You can name :chef_id whatever your like but I think it is pretty normal name.

Rails: How to enter value A in Model X only if value A exists in Model Y?

I'm trying to build a registration module where user can only register if their e-mail is already in an existing database.
Models:
User
OldUser
The condition on User will be
if OldUser.find_by_email(params[:UserName]) exists, allow user registration.
If not, then indicate error message.
This is really simple to do in PHP where I can just run a function to execute a mysql query. However, I couldn't figure out how to do it on Rails. It looks like I have to create a custom validator function but seems to be overkilled for a such simple condition.
It should be pretty simple to do. What have I missed?
Any pointer?
Edit 1:
This solution by dku.rajkumar works with a slight modification:
validate :check_email_existence
def check_email_existence
errors.add(:base, "Your email does not exist in our database") if OldUser.find_by_email(self.UserName).nil?
end
For cases like this, is it better to do validation in the model or at the controller?
you can do it as
if OldUser.find_by_email(params[:UserName])
User.create(params) // something like this i guess
else
flash[:error] = "Your email id does not exist in our database."
redirect_to appropriate_url
end
UPDATE: validation in model, so the validation will be done while calling User.create
class User < ActiveRecord::Base
validates :check_mail_id_presence
// other code
// other code
private
def check_mail_id_presence
errors.add("Your email id does not exist in our database.") if OldUser.find_by_email(self.UserName).nil?
end
end
I'd recommend starting with Devise.
See https://github.com/plataformatec/devise
Even if you have unusual needs like these, you can normally adapt it. Once you get to know it, it's extremely powerful, solid and debugged, and you can do all sorts of things with it.
Bellow is just an initial implementation .../app/controller/UsersController for User registration related actions.
def new
#user = User.new
end
def create
#user = User.new(params[:user])
#old_user = User.find_by_email(user.email)
if #old_user
if #user.save
# Handle successful save
else
render 'new' # and render some error message telling why registration was not succeed
end
else
# render some page with some sort of error message of 'new' new users
end
end
Update:
Check out the following resources for more info:
Ruby on Rails Tutorial
Rails: User/Password Authentication from Scratch, Part I/II

Instance variable not working in rails model

I am trying to create persistante variable local to my model but although something that sounds so simple is not working.
I have this in my model:
class Coupon < ActiveRecord::Base
#username = "empty"
#admin = false
def self.setUser(name, isAdmin)
#username = name
#admin = isAdmin
end
def self.get_user (user)#an attempt to access the current_user but did not work i call this from the controller (I understand it is not best practice)
##user = user
self.setUser(user.username,user.admin?)
end
def has_not_occurred
errors.add("property_of","name is not valid:#{#username}") if !validPropertyOf?
end
end
def validProperty_of?
return property_of == #username # || #Admin
end
end
I actually get a "" instead of "empty" or the new value of username in set.user. How do I make these values persist? I have printed the values inside each method so they persist inside the method but not beyond for some reason.
#username is always nil or "" when it gets to has_not_accurred.
Why is this and how do I make it persist? Thank you so much.
I cannont access #user when I set it either (get_user method). I get a nil instance later down at validateProperty_of
I think you forget about database table, you haven't create this one, that's why every variables are non-persistent.
Upgraded Rails now it works. Not sure why.

Problem with Active Record Querying

I am building a little application in Rails and what I am trying to do now is authenticate a user.
So I got this method in the controller class:
def login
if #user = User.authenticate(params[:txt_login], params[:txt_password])
session[:current_user_id] = #user.id
redirect_to root_url
end
end
Here is the definition of authenticate method (inside the User model class):
def self.authenticate(username, password)
#user = User.where(["username = ? AND password = ?", username, password])
return #user
end
The problem is that I get an error message saying:
undefined method `id' for #<ActiveRecord::Relation:0x92dff10>
I confirm that the user I was trying to log in really exists in the database (besides it tries to get the id of a user and this instruction is wrapped inside an if in case 0 users are returned from the authenticate method).
Why am I obtaining this error message? Knowing that when I change the User.where by User.find it works fine!
Thank you!
User.where("some_conditions") will return an array of User objects ( in simple terms ) , A User.find can return an array or a single object.( I am not sure because i don't see how you are using it )
As far what you see is ActiveRecord::Relation, this is what is returned when we call a find or a where or a order method on Rails 3 Models.
Also, You are storing password as a plain string which is a bad idea, you should use some available rails authentication plugins like Devise or Authlogic.

Resources