ActiveRecord é uma das engines dentro do core Rails, que trás consigo a implementação de um ORM (Object Relational Mapping), que é um conceito dentro da arquitetura de software na qual utilizamos técnicas de programação para converter/lidar com dados entre o banco de dados e a programação orientada a objetos, nesse caso, utilizando Ruby.
Ruby on Rails é um poderoso framework MVC que trás consigo várias soluções flexiveis e inteligentes para problemas já conhecidos dentro do desenvolvimento back-end.
Podemos citar algumas soluções que vem trazendo bastante poder aos desenvolvedores, porém hoje, trago uma funcionalidade que podemos utilizar nativamente em Rails, visto que vamos utilizar a RailsEngine::ActiveRecord
O funcionamento por “baixo dos panos” é poder fazer queries em SQL puro, porém utilizando os conceitos e métodos através de uma linguagem padrão.
Scopes em Ruby on Rails
• O que são scopes?
Geralmente utilizamos scopes para construir queries personalizadas dentro das entidades modelo da aplicação, e além disso, podemos utilizar o scope criado como um método de classe. Assim, fazemos uso desses scopes como qualquer outro método presente no ActiveRecord.
Sintaxe e parâmetros
Todo scope precisa receber dois argumentos, são eles:
• 1. Um nome, que será usado para chamar este scope no código.
• 2. Uma lambda, que implementa a query.
A sintaxe de um scope é definido por:
scope :name_of_your_scope, -> { where(“column_name = ?”, value)}
Também podemos passar diferentes parâmetros para utilizarmos ao fazer as nossas buscas. Para elucidar o conceito, suponhamos que seja necessário buscar em uma base de dados, os usuários que foram criados nos ultimos 30 dias.
Podemos declarar o scope para receber o parametro date da seguinte maneira:
class User < ApplicationRecord
scope :get_users_by_date, -> (date) { where(*"created_at > ?"*, 30.days.ago if date.nil?) }
end
Caso não seja passado nenhuma data, colocamos por padrão 30 dias a partir do dia de hoje.
Como resultado da chamada deste scope, recebemos um objeto do tipo ActiveRecord::Relation
. Isso significa que podemos encadear e combinar diferentes scopes. Também, em termos de funcionalidade, o scope garante que erros sejam evitados caso o retorno da nossa query venha vazio.
Scopes com SQL puro
Outro jeito válido de declararmos scopes, é utilizando queries com SQL puro, assim conseguimos passar um ou mais parâmetros no scope e utilizá-los dentro da query, e claro, evitando injeção de outros parâmetros desnecessários na busca.
class User < ApplicationRecord
scope :find_by_range_date, -> (start_date, end_date) { where(”created_at >= ? AND created_at <= ?“, start_date, end_date)}
end
Scope vs Default Scope
Quando declaramos um default_scope
, garantimos que por padrão, essa query será aplicada automaticamente em nosso modelo.
class User < ApplicationRecord
default_scope { where(admin: true) }
end
Esse comportamento redefine por padrão o método .all
do nosso modelo, portando devemos evitar seu uso, visto que alguns erros e tempo de depuração não sejam perdidos.
Conclusão
Um dos grandes potenciais do Rails é poder combinar ou encadear outros scopes diferentes, assim podemos criar queries mais fáceis de ler, ex:
def index
date = Date.new(12/21/2021)
@users = User.sort_by_creation(date).some_other_scope.where.not(role: admin)
end
Assim, ao utilizarmos outros scopes e até os métodos padrões do ActiveRecord, podemos separar de forma mais limpa e clara, as responsabilidades e funcionalidades de cada query presente **nos modelos.
Outro ponto que não abordei ao longo deste guia, foi o uso de Lambdas para escrevermos os scopes utilizando apenas uma linha. Isso acontece pois a lambda é um objeto do tipo Proc. Basicamente, um proc, é um objeto que encapsula um bloco de código, exemplo:
lambda = ->(x) { x**2 }
lambda = Proc.new {|x| x**2 }
Ao fazer lambda.(3)
ou lambda.call(3)
em ambas as variavéis, vamos receber o resultado 9. Mas isso deixo pra abordar em meu proximo aprendizado, até mais, nos vemos lá!
Top comments (0)