Desde a versão 4.0 do Rails temos disponível no Active Record o método: where.not
. Com ele é possível simplificar algumas queries. Vamos usar como exemplo uma aplicação onde temos carros para locação e, para isso, registramos Fabricantes pelo model Manufacturer
. Se rodarmos no console:
$ Manufacturer.all
Manufacturer Load (0.3ms) SELECT "manufacturers".* FROM "manufacturers" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[#<Manufacturer id: 1, name: "Fiat", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">,
#<Manufacturer id: 2, name: "Ford", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">,
#<Manufacturer id: 3, name: "Toyota", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">]>
Para realizarmos uma query que retorna os fabricantes com nomes diferentes de "Fiat" poderíamos rodar:
$ Manufacturer.where("name != ?", "Fiat")
Manufacturer Load (0.6ms) SELECT "manufacturers".* FROM "manufacturers" WHERE (name != 'Fiat') LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[#<Manufacturer id: 2, name: "Ford", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">,
#<Manufacturer id: 3, name: "Toyota", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">]>
E este seria o mesmo resultado se usássemos:
$ Manufacturer.where.not(name: "Fiat")
Manufacturer Load (0.8ms) SELECT "manufacturers".* FROM "manufacturers" WHERE "manufacturers"."name" != ? LIMIT ? [["name", "Fiat"], ["LIMIT", 11]]
=> #<ActiveRecord::Relation
[#<Manufacturer id: 2, name: "Ford", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">,
#<Manufacturer id: 3, name: "Toyota", created_at: "2020-07-09 17:47:13", updated_at: "2020-07-09 17:47:13">]>
As queries executadas no banco são ligeiramente diferentes, mas os resultados obtidos são os mesmos. A principal diferença é que o where.not
permite ao Rails aproveitar mais recursos de Prepared Statements, mas isso é assunto para outro texto =)