Métodos do Controller
O Nerdify::ApplicationController fornece métodos auxiliares para manipular objetos, critérios de busca e renderização de páginas.
Métodos de Acesso a Objetos
object
Retorna o objeto atual (para show, edit, new, create, update, destroy):
def approve
object.update(status: "approved")
render json: { success: true }
end
O método automaticamente:
- Busca o objeto por ID em show/edit/update/destroy
- Cria uma instância nova em new/create
- Atribui
current_userecurrent_ability - Captura associações de parents (via parâmetros
*_id)
objects
Retorna a coleção de objetos (para index):
def index
# objects retorna Model.accessible_by(current_ability).and(criteria)
super
end
O método automaticamente:
- Aplica
accessible_by(current_ability)para autorização - Aplica o
scopeeorder_scopedefinidos - Aplica os
criteriados filtros - Aplica busca full-text se
search_parampresente
model
Retorna a classe do modelo baseado no nome do controller:
# Em Api::V1::CustomersController
model # => Customer
symbol
Retorna o símbolo do modelo:
# Em Api::V1::CustomersController
symbol # => :customer
variable
Retorna o nome da variável de instância:
# Em index
variable # => "@customers"
# Em show
variable # => "@customer"
Métodos de Critérios
criteria
Converte os parâmetros de filtro em critérios de busca MongoDB:
# Request: /customers?filters[status]=active&filters[city]=São Paulo
criteria
# => { status: "active", city: "São Paulo" }
O método automaticamente:
- Remove parâmetros internos (
_,page,action, etc) - Converte arrays:
["a","b"]→{ "$in" => ["a","b"] } - Converte operadores:
field.gte=10→{ field: { "$gte" => 10 } } - Converte booleanos:
"true"→true - Adiciona critérios de parents
scope
Retorna o scope a ser aplicado:
def default_scope
:active
end
# Se params[:filters][:scope] = "pending"
scope # => "pending"
# Se não houver filtro
scope # => :active
search_param
Retorna o parâmetro de busca full-text:
# Request: /customers?filters[search]=João
search_param # => "João"
Métodos de Parents
get_parents
Retorna os objetos parent da URL aninhada:
# Request: /customers/123/pets/456
get_parents # => [#<Customer id: 123>]
set_parents
Configura os parents a partir dos parâmetros *_id:
# Chamado automaticamente
# Cria @customer a partir de customer_id
set_parents
Métodos de Parâmetros
parameters
Retorna todos os parâmetros como hash:
parameters
# => { controller: "...", action: "...", id: "...", customer: { name: "..." } }
object_parameters
Retorna os parâmetros permitidos do modelo:
# Request: { customer: { name: "João", email: "joao@email.com" } }
object_parameters
# => { name: "João", email: "joao@email.com" }
O método:
- Aplica
permitcom os campos permitidos do modelo - Converte tipos especiais (money, date)
Métodos de Renderização
page_json
Gera o JSON completo da página:
def show
render json: page_json
end
Estrutura retornada:
{
request: { path: "/customers/123" },
resources: {
customer: { id: "123", name: "João", ... },
current_user: { id: "1", name: "Admin", ... },
filters: {},
params: {}
},
components: [
{ type: "fieldset", name: "customer_form", ... }
],
translations: {
"name" => { "name" => "Nome", "placeholder" => "..." }
},
options: {
layout: "default",
pagination: { customers: { per_page: 25, total_count: 100 } }
}
}
respond_to_api_with
Renderiza a resposta baseada na action:
def show
respond_to_api_with(object)
end
Métodos de Autorização
current_ability
Retorna a instância de Ability para o usuário atual:
current_ability # => #<Ability:...>
authorization?
Verifica se autorização está habilitada:
if authorization?
objects.accessible_by(current_ability)
end
Callbacks
after_create
Executado após criar um registro:
def after_create
# Lógica pós-criação
end
after_update
Executado após atualizar um registro:
def after_update
# Lógica pós-atualização
end
after_destroy
Executado após excluir um registro:
def after_destroy
# Lógica pós-exclusão
end
Exemplo de Controller Customizado
class Api::V1::OrdersController < Nerdify::ApplicationController
authenticate User, auth_path: "users/sign_in"
template "nerdify/templates/application"
# Scope padrão
def default_scope
:pending
end
# Ordenação padrão
def default_order
:recent
end
# Adiciona recursos extras ao JSON
def page_json(action = nil)
json = super(action)
if params[:action] == "show"
json[:resources][:available_products] = Product.active.map(&:as_json)
end
json
end
# Action customizada
def approve
if object.can_approve?
object.update(status: "approved", approved_by: current_user)
render json: {
success: true,
toast: "Pedido aprovado!",
redirect_to: "/orders/#{object.id}"
}
else
render json: {
success: false,
errors: object.errors.full_messages
}, status: :unprocessable_entity
end
end
# Sobrescreve critérios
def criteria
base = super
# Adiciona filtro de loja do usuário
if current_user.store_id.present?
base[:store_id] = current_user.store_id
end
base
end
end
Boas Práticas
Faça
- Use
objecteobjectsao invés de queries diretas - Sobrescreva
page_jsonpara dados contextuais - Use
default_scopepara filtros padrão por perfil - Mantenha actions customizadas simples
Evite
- Queries complexas dentro das actions
- Ignorar
accessible_bypara autorização - Modificar
objectsem validação - Retornar dados sensíveis em
page_json