Devise - NoMethodError Undefined method `+' for NilClass - ruby-on-rails

Trying to reset password I get an error NoMethodError Undefined method `+' for NilClass. I guess it may be due to a devise method
def confirmation_period_expired?
self.class.confirm_within && (Time.now > self.confirmation_sent_at + self.class.confirm_within )
end
because confirmation_sent_at still nil in db. I wonder why
def generate_confirmation_token
self.confirmation_token = self.class.confirmation_token
self.confirmation_sent_at = Time.now.utc
end
doesn't set confirmation_sent_at. No idea why, but generate_confirmation_token isn't called. Any thoughts?

Probably you got the error
def confirmation_period_expired?
total_sent_at = (self.confirmation_sent_at.nil? || self.class.confirm_within.nil?) ? 0.0 : (self.confirmation_sent_at + self.class.confirm_within)
self.class.confirm_within && (Time.now > total_sent_at )
end
you can also use try

Try
def generate_confirmation_token
self.confirmation_token = self.class.confirmation_token
self.confirmation_sent_at = Time.now.utc
# you dont save your instance
save
# now saved
end

It was due the old version of Devise. In previous Devise versions (< 3.1.0), resetting the password automatically confirmed user accounts without sending confirmation. More here http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/

Related

How to manage dates in Custom Validations in Rails

Hello Devs I'm trying to compare dates in a custom validator, but it seems that i'm not doing it properly.
i need to make a condition for a document, if 90 days have passed since the date of expiration, if its true then return an error.
class CheckDocumentValidator < ActiveModel::Validator
def validate(record)
expiration_date = record.expiration_date
actual_date = Time.current
diff = ((actual_date - expiration_date.to_time)/3600).round
days_diff = diff/24
if days_diff > 90
record.errors.add(:expiration_date, "error")
end
end
end
expiration_date is a date attribute on my model AttachmentInstance
In the logs says that -- Error: undefined method `to_time' for nil:NilClass
i think the error
Error: undefined method `to_time' for nil:NilClass
is because no data found on record.expiration_date.
if record.expiration_date is Time class. it should be like this
if record.expiration_date + 90.day > Time.now
record.errors.add(:expiration_date, "error")
end

Rails 5 ActiveRecord - check if any results before using methods

In my Rails 5 + Postgres app I make a query like this:
user = User.where("name = ?", name).first.email
So this gives me the email of the first user with the name.
But if no user with this names exists I get an error:
NoMethodError (undefined method `email' for nil:NilClass)
How can I check if I have any results before using the method?
I can think if various ways to do this using if-clauses:
user = User.where("name = ?", name).first
if user
user_email = user.email
end
But this does not seem to be the most elegant way and I am sure Rails has a better way.
You can use find_by, returns the object or nil if nothing is found.
user = User.find_by(name: name)
if user
...
end
That being said you could have still used the where clause if you're expecting more than one element.
users = User.where(name: name)
if users.any?
user = users.first
...
end
Then there is yet another way as of Ruby 2.3 where you can do
User.where(name: name).first&.name
The & can be used if you're not sure if the object is nil or not, in this instance the whole statement would return nil if no user is found.
I use try a lot to handle just this situation.
user = User.where("name = ?", name).first.try(:email)
It will return the email, or if the collection is empty (and first is nil) it will return nil without raising an error.
The catch is it'll also not fail if the record was found but no method or attribute exists, so you're less likely to catch a typo, but hopefully your tests would cover that.
user = User.where("name = ?", name).first.try(:emial)
This is not a problem if you use the Ruby 2.3 &. feature because it only works with nil object...
user = User.where("name = ?", name).first&.emial
# this will raise an error if the record is found but there's no emial attrib.
You can always use User.where("name = ?", name).first&.email, but I disagree that
user = User.where("name = ?", name).first
if user
user_email = user.email
end
is particularly inelegant. You can clean it up with something like
def my_method
if user
# do something with user.email
end
end
private
def user
#user ||= User.where("name = ?", name).first
# #user ||= User.find_by("name = ?", name) # can also be used here, and it preferred.
end
Unless you really think you're only going to use the user record once, you should prefer being explicit with whatever logic you're using.

Add to Integer Variable from Rails Controller

This should be a fairly simple error to fix (I hope). When a joke on my app is approved, I want that user to be awarded 5 manpoints (don't ask). I currently have this in my 'jokes_controller`:
def approve
#joke = Joke.find(params[:id])
#joke.update_attributes(approved: true)
if #joke.user.manpoints = nil
#joke.user.manpoints = 5
else
#joke.user.manpoints += 5
end
#joke.save
redirect_to jokes_path
end
I'm getting this error when I try to approve a joke:
undefined method `+' for nil:NilClass
I thought += was the "Ruby way" to do this? Can anyone set me straight?
Change = in if condition to ==. I assume you need to compare manpoints with nil, not to assign nil to manpoints.
It should be like:
if #joke.user.manpoints == nil
...
You can omit == operator here:
unless #joke.user.manpoints
...
PS. Why are you excepting that manpoints will be nil?

undefined method `empty?' for nil:NilClass how to avoid it

Hi Together I've got this code:
#coursesFound = #user.available_courses
#courses = []
for course in #coursesFound do
#courseInGroups = course.user_groups
for group in #courseInGroups do
#group = UserGroup.find group.id
if #group.users.map { |u| u.id }.include? #user.id
#courses << course
break
end
end
end
# Wenn ein Kurs keiner Gruppe hinzugefügt wurde
if #courseInGroups.empty?
#courses << course
end
on my debian vm it works fine but on my live system I got this error:
undefined method `empty?' for nil:NilClass
How can I avoid this?
If this #coursesFound = #user.available_courses returns an empty activerecord relation.
Then this won't execute
for course in #coursesFound do
#courseInGroups = course.user_groups
for group in #courseInGroups do
#group = UserGroup.find group.id
if #group.users.map { |u| u.id }.include? #user.id
#courses << course
break
end
end
end
Which means when you get here #courseInGroups is nil
if #courseInGroups.empty?
#courses << course
end
So your quick fix would be
if #courseInGroups && #courseInGroups.empty?
#courses << course
end
You can use the try method to Avoid this error:
#courseInGroups.try(:empty?)
This won't throw an error if #courseInGroups was nil.
And don't forget blank? when using rails. Here you find a good overview of all methods with or without rails.
I did not analyze your code, it's just for you, me and others that do not use this methods often, mix them up and then come here - just to remember: empty? is not blank?.
You need to properly initialize your object as well.
#courseInGroups = course.user_groups || []
You won't get nil:NilClass error any more if you initialize properly.
To get rid of nil:NilClass error you can use other answer. like try etc.
You can put the ? before the dot of the empty:
if #courseInGroups?.empty

Errors like "NoMethodError: undefined method `sweep' for #<Hash …" after downgrading to Rails 3 from Rails 4

We upgraded to Rails 4, had some major issues and downgraded again (reverted the upgrade commit).
We then got errors like
NoMethodError (undefined method `sweep' for #<Hash:0x007f01ab44a940>):
seemingly because Rails 4 stores a flash in the session in a way that Rails 3 can't read.
What is a good way to solve this?
We ended up solving this by patching Rails itself to catch this error and delete the borked flash. This means that it self-heals quite transparently.
We also made sure to only apply this patch on Rails 3, so it doesn't cause issues when we make another attempt at upgrading to Rails 4.
We stuck this in config/initializers/rails4_to_rails3_downgradability.rb:
if Rails::VERSION::MAJOR == 3
module ActionDispatch
class Flash
def call(env)
if (session = env['rack.session']) && (flash = session['flash'])
# Beginning of change!
if flash.respond_to?(:sweep)
flash.sweep
else
session.delete("flash")
end
# End of change!
end
#app.call(env)
ensure
session = env['rack.session'] || {}
flash_hash = env[KEY]
if flash_hash
if !flash_hash.empty? || session.key?('flash')
session["flash"] = flash_hash
new_hash = flash_hash.dup
else
new_hash = flash_hash
end
env[KEY] = new_hash
end
if session.key?('flash') && session['flash'].empty?
session.delete('flash')
end
end
end
end
end
Faced the same issue, resolved by telling users to clear cookies. Might not a solution for everyone, just pointing out that it's an option.

Resources