_skinnycontrollers is a thin layer on top of rails with the goal of allowing for much easier unit-testability, inspired by ember
A demo app can be found in the spec here.
An implementation of role-based policies and operations to help controllers lose weight.
The goal of this project is to help API apps be more slim, and separate logic as much as possible.
If you have an idea or suggestion for improved defaults, please submit an issue or pull request. :-)
render json: model
render json: model
will give you default CRUD functionality in your controller actions.current_user
is allowed to perform an action on an object.gem 'skinny_controllers'
or
gem install skinny_controllers
include SkinnyControllers::Diet
# ...
# in your action
render json: model
and that's it!
Sometimes, magic is scary. You can call anything you want manually (operations and policies).
Here is an example that manually makes the call to the Host Operations and passes the subdomain parameter in to filter the Host
object on the subdomain.
def show
render json: host_from_subdomain, serializer: each_serializer
end
private
def host_from_subdomain
@host ||= HostOperations::Read.new(current_user, params, host_params).run
end
def host_params
params.permit(:subdomain)
end
The parameters for directly calling an operation are as follows:
# | Parameter | Default when directly calling an operation | Implicit default | Purpose |
---|---|---|---|---|
0 | current_user | n/a | current_user |
the user performing the action |
1 | controller_params | n/a | params |
the full params hash from the controller |
2 | params_for_action | controller_params |
create_params , index_params , etc |
e.g.: requiring a foreign key when looking up index |
3 | action | controller_params[:action] |
action_name |
the name of the current action |
4 | options | {} |
skinny_controllers_config options |
Strong parameters must be used on create/update actions.
Here is an example params method
private
def event_params
params
.require(:data)
.require(:attributes)
.permit(:name)
end
Note that we don't need the id under the data hash, because in a RESTful api, the id will be available to us through the top level params hash.
This may not be horribly apparent, but here is a table overviewing some highlevel differences
Feature | - | skinny_controllers | trailblazer | |
---|---|---|---|---|
Purpose | - | API - works very well with ActiveModel::Serializers | General - additional features for server-side rendered views | |
Added Layers | - | Operations, Policies | Operations, Policies, Forms | |
Validation | - | stay in models | moved to operations via contract block | |
Additional objects | - | none | contacts, representers, callbacks, cells | |
Rendering | - | done in the controller, and up to the dev to decide how that is done. ActiveModel::Serializers with JSON-API is highly recommended |
- | representers provide a way to define serializers for json, xml, json-api, etc |
App Structure | - | same as rails. app/operations and app/policies are added |
encourages a new structure 'concepts', where cells, view templates, assets, operations, etc are all under concepts/{model-name} |
Please refer to each project's style guidelines and guidelines for submitting patches and additions. In general, we follow the "fork-and-pull" Git workflow.