Open wilkinsondarolt opened 5 years ago
Olá tenho uma sugestão que tenho usados em meus projetos, este é exemplo usando em um controller 'normal' mas é facilmente adaptado para fazer api, usando ActiveModelSerializer/Paginação/Ransack etc.
Criei um concern chamado Resoursable
module Resourceable
extend ActiveSupport::Concern
included do
before_filter :set_resource, only: [:show, :edit, :update, :destroy]
before_filter :authorize_resource
helper_method :resource
class_attribute :model, :model_attribute_name, :resource_actions,
:relationships, :permitted_parameters, :order
end
class_methods do
# Define the ActiveModel::Base served by this resource controller.
def serve(model, relationships: [], parameters: [], order: {id: :desc})
self.model = model
self.model_attribute_name = "@#{model.to_s.underscore}"
self.relationships = relationships
self.permitted_parameters = parameters
self.order = order
end
end
def index
@search = policy_scope(model)
.ransack(params[:q])
@resources = @search.result.distinct
.includes(relationships)
.paginate(page: params[:page], per_page: params[:per_page])
.order(order)
respond_with @resources
end
def show; end
def new
instance_variable_set model_attribute_name, resource_build
respond_with resource
end
def edit; end
def create
instance_variable_set model_attribute_name, resource_build
resource.assign_attributes resource_params
if resource.save
flash[:success] = I18n.t('flash.actions.create.notice')
else
flash[:error] = resource.errors.full_messages
end
respond_with resource
end
def update
if resource.update(resource_params)
flash[:success] = I18n.t('flash.actions.update.notice')
else
flash[:error] = resource.errors.full_messages
end
respond_with resource
end
def destroy
if resource.destroy
flash[:success] = I18n.t('flash.actions.destroy.notice')
else
flash[:error] = I18n.t('flash.actions.destroy.alert')
end
respond_with resource, location: resources_path
end
def destroy_all
if policy_scope(model).destroy_all
flash[:success] = I18n.t('flash.actions.destroy_all.notice')
else
flash[:error] = I18n.t('flash.actions.destroy_all.error')
end
redirect_to resources_path
end
def settings; end
private
def resources_path
polymorphic_path model
end
def resource_path
polymorphic_path resource
end
def resource_build
model.new
end
def resource
instance_variable_get(model_attribute_name)
end
def set_resource
instance_variable_set model_attribute_name,
policy_scope(model).
includes(relationships).
find(params[:id])
end
def authorize_resource
authorize(resource || model)
end
def resource_params
params.require(model.to_s.underscore.to_sym).permit permitted_parameters
end
end
E nos controller eu faço algo do tipo:
class TasksController < ApplicationController
include Resourceable
before_filter :set_create_by, only: [:create]
before_filter :set_closed_at, only: [:update]
serve Task,
parameters: [ :title, :description, :status, :due_date,
:created_by_id, :closed_at, :attendance_id,
{ user_ids: [] }
],
relationships: [:users],
order: { due_date: :desc }
def resource_build
model.new resource_params
end
private
def set_create_by
params[:task][:created_by_id] = current_user.id
end
def set_closed_at
params[:task][:closed_at] = DateTime.current if !@task.closed? && params.dig(:task, :status) == 'closed'
end
end
class ProductItemsController < ApplicationController
include Resourceable
serve ProductItem,
parameters: [:part_number, :description, :base_price, :product_type_id],
order: {description: :asc}
end
Isso facilitaria no test com pois pderia fazer algo com https://relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples mas fui inventar de usar minitest e ainda não sei como fazer algo parecido.
Ha claro isso poderia fazer parte da refatoração dos controllers de vcs tbm como previsto n issue #9
Att
Avaliar problemas de
Em um dos arquivos da pasta
app/controllers/api/v2
Seguindo as práticas descritas em nosso style guide