-2

Faced a problem completely incomprehensible to me. I am getting an error when using the method where.

@winner = Team.where(id: params[:winner_id])
@winner.update(rating: @winner.rating += 20)
undefined method `rating' for #<Team::ActiveRecord_Relation:0x00007faed9018490>

However, if I change @winner = Team.where(id: params[:winner_id]) to @winner = Team.find(params[:winner_id])it will work.

Why where method doesn't work?

SsPay
  • 177
  • 1
  • 10

1 Answers1

3

Because where always gives you an ActiveRecord_Relation, not a single object. In your case you're filtering on the id, so if that's the primary key, as I suppose, you only get one record, but that's into a relation anyway, because that's the semantic of where.

@winner = Team.where(id: params[:winner_id]).first

or

@winner = Team.find_by(id: params[:winner_id])

One of these should do the trick

where works this way because you could even filter for some not so restrictive columns and get many rows in returns, so you always get a collection of rows. For example, think about this

@people = Person.where(age: 20)

this query retrieves all the people 20 years old. That could get zero, one or many rows but you always get a relation, for sure.

Ursus
  • 29,643
  • 3
  • 33
  • 50
  • I didn't quite understand what it means _always get a relation_. I have used `where` unmeasured number of times and have never encountered this. – SsPay Aug 12 '20 at 15:46
  • With `where` you don't get a single object but a collection of objects. It's the method's semantic. – Ursus Aug 12 '20 at 15:47
  • @SsPay: "and have never encountered this" - if this is true, you have never tried to call a method which belongs to a model on a result of `where` before. – Sergio Tulentsev Aug 12 '20 at 16:04
  • @Ursus: you don't even get a "collection of objects". There are no objects. Instead you get this weird collection-like proxy thingie that goes and fetches data from the db, but only if you attempt to iterate it. If you never iterate, it won't make a query. But this is too fine a level of details, I suppose :) – Sergio Tulentsev Aug 12 '20 at 16:07
  • @SergioTulentsev I was trying to keep it is as simple as possible :( – Ursus Aug 12 '20 at 16:09
  • @Ursus: yeah-yeah, it walks like a duck and quacks like a duck. For practical purposes, it's a duck (collection). – Sergio Tulentsev Aug 12 '20 at 16:10
  • @Sergio Tulentsev I mean I used 'where' along with the primary key (id). And I expected to get only one result, not an array, since there cannot be two objects with the same id. – SsPay Aug 12 '20 at 17:12
  • 1
    @SsPay that's simply not how `where` works :) if you use `where` you're accepting the fact that what it returns is a collection. Otherwise you use find_by or find or where + first – Ursus Aug 12 '20 at 17:20