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

      

+3


source to share


7 replies


Try the following:



@user.increment :books_on_loan, 1

      

+1


source


You can try the following codes which will handle nil value for @ user.books_on_loan

  @user.books_on_loan = @user.books_on_loan.to_i + 1

      

or



  @user.books_on_loan = (@user.books_on_loan || 0) + 1

      

or



  @user.books_on_loan = (@user.books_on_loan.present? ? @user.books_on_loan : 0)  + 1

      

+1


source


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.

+1


source


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

0


source


Just follow through @user.books_on_loan.to_i

. to_i automatically converts nil to 0

0


source


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.

0


source


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

0


source







All Articles