Integer increments / decrees in user model by 1
I have a user model that has these columns - name, email, books_on_loan
I have a booking system where users can view / post books. When a user checks out a book, I want to increase their books_on_loan_ number by one and vice versa.
So far I've tried it this way and get the error "undefined method '+' for nil: NilClass" - it doesn't like @ user.books_on_loan
def check_out
@params = params[:book]
title = @params[:title]
name = @params[:name]
@book = Book.find_by_title(title)
@user = User.find_by_name(name)
if @user == nil
@note = 'This user is not registered.'
elsif @book == nil
@note = 'This book is not in the library.'
elsif @book.onloan == 1
@note = 'This book is on loan.'
elsif @user.books_on_loan == 3
@note = 'This user already has 3 books out.'
else
@book.onloan = 1
@book.save
@books_loaned = BooksOnloan.create(book_id: @book.id, user_id: @user.id)
@books_loaned.save
@user.books_on_loan = @user.books_on_loan + 1
@user.save
@note = 'The book was checked out.'
end
respond_to do |format|
format.html
end
end
source to share
While most of the answers here are okay, you would rather change the root of the problem , otherwise you will have to use the defense reasons in your application.
Seems to be books_on_loan
an attribute in db, so:
change_column :users, :books_on_loan, :integer, default: 0
#and change existing bad data
User.update_all({books_on_loan: 0}, {books_on_loan: nil})
Or you can change the receiver in your class:
def books_on_loan
super || 0
end
Side note, design wise, it doesn't matter if it's a good idea to have an integer in the db while maintaining current books on loan: you might get out of sync with the real ones.
You would rather consider it a real connection.
source to share
Your user on startup has no books on boot, but db
it is not set as 0
, but nill
. So change the line of code
@user.books_on_loan = @user.books_on_loan + 1
from
@user.books_on_loan = (@user.books_on_loan || 0) + 1
If @user.books_on_loan
is nil it will use 0
and your method +
will fail
source to share
The ost answers are very correct, but I would like to add the following.
To answer your question, incrementing the value of an attribute (even for a variable that returns nil
) can be done like this:
@user.books_on_loan =+ 1
decrease: @user.books_on_loan =- 1
However, you can take advantage of the corresponding model associations here and have a has_many -> relationship between User and Book , where adding / deleting a book for the user, the counter is configured accordingly.
source to share
Rails provides a practical abstraction that you can use: increment
and decrement
. So now you can do something like this:
@user.increment(:books_on_loan, 1)
The increment takes 2 arguments. Column of the table and the number by which you are incrementing. It initializes the attribute to zero if nil and appends the value passed as (default is 1).
In a similar way, you can use
@user.decrement(:book_on_loan, 1)
Read more about it HERE
source to share