-
Notifications
You must be signed in to change notification settings - Fork 1
Home
These are the regular Ruby on Rails (API) building blocks:
- Controllers
- Channels
- Helpers
- Mailers
- Models
- Views (Or the API equivalent; serializers)
LinkedRails extends upon the Rails toolkit by adding some new blocks and extending others.
LinkedRails extracts the following blocks as first-class citizens:
- Enhancements; a simple way to add a specific behaviour to a model
- Actions; define what you can do with a model
- Forms; define how your users enter information
- Policies; define rules what should be allowed
LinkedRails adds the following extensions:
- Collections; like
has_many
but more extendible and powerful
Enhancements provide an interface to encapsulate all aspects of a specific functionality into a module
Lots of behaviour is shared across models, controllers, and views. For example; Rails allows us to keep track of create/update times, most apps allow users to create and edit models, have some view template for showing an item in a list. There are multiple ways to abstract this behaviour, ruby modules or ActiveSupport Concern for example.
Though none of these options went far enough, which is what enhancements aim to fix. Enhancements allow you to define (nearly) all aspects of a shared behaviour in a concise way.
Because enhancements are meant to encapsulate a certain behaviour, we have a convention to name all enhancements by conjugating the base with the -able suffix, so Update
becomes Updatable
, Convert
becomes Convertible
(note the i
).
Enhancements are placed in their own folder and have a certain structure:
app/enhancements/<enhancement_name>
:
action.rb
controller.rb
model.rb
policy.rb
routing.rb
serializer.rb
Each file contains a module EnhancementName::Segment
(E.g. Creatable::Controller
) with the code needed for the task.
To enable a specific enhancement for a model, just declare it in the model
class BlogPost < ApplicationModel
enhance Creatable
end
After which all the modules will be included in the appropriate objects, in the case of Creatable
the BlogPostsController
will now contain both a new
and create
method. The only thing we have to do to fill-in the details; define our form and permissions and you can start creating blog posts.
If you need different behaviour for a certain model, you can override an enhancements' behaviour by overriding methods in the appropriate location (e.g. the model or controller).
Though not to be confused with controller actions directly, Actions can be seen as an abstraction of these. Actions give interaction capabilities to the system and encapsulate everything that a client needs to fulfil it, this includes the url and HTTP method, a name, a form, a policy, conditions, the result, the status, etc. The base of the actions are schema:Action with some additions like a form.
Since most models have many actions, they are defined in action lists rather than separately. Actions from enhancements are automatically defined, in addition custom actions can be defined by specifying them in the action list.
class BlogPostActionsList < ApplicationActionList
has_action(
:publish,
type: NS::APP[:PublishAction],
policy: :publish?,
http_method: :put,
image: 'fa-send',
include_object: false,
url: (obj)-> { publish_blog_post_url(obj) },
condition: -> { !resource.publication&.publish_time_lapsed? }
)
end
Due to user-experience requirements there is often a difference between what data you store and how entering that data is presented to the user. Often forms don't show all fields or they've been broken into multiple pages. LinkedRails includes a DSL to declare powerful (reusable) forms.
Given the following (simplified) model
class BlogPost < ApplicationModel
enhance Attachable
field :name,
presence: true,
length: {maximum: 100}
field :text, presence: true
end
and the following form
class BlogPostForm < ApplicationForm
enhance Attachable
field :name
field :text,
datatype: NS::FHIR[:markdown]
has_many :attachments
group :advanced label: 'Options' do
field :theme,
datatype: NS::XSD[:string],
max_count: 1,
input_field: LinkedRails::Form::Field::SelectInput,
sh_in: %i[general programming cooking]
end
end
Note that each model can have a default form (ModelNameForm
), but isn't limited to it, which forms you create is up to your UX requirements.
A form has three elements; fields, associations, and groups. In addition, form-specific information can be added like the input type. LinkedRails will automatically try to take extra information from the object passed to the form.
LinkedRails integrates the the pundit gem to define resource policies.
Controllers have been highly standardized, but the behaviour can be changed by overriding certain methods.
Method name | Type | Description |
---|---|---|
serializer_params | Hash | Object given to the serializers |
<action_name>_includes | Array | List of property names to include with a #action_name response |
preview_includes | Array | List of property names to include from the members of the collection |
To enable include the following in the Rails base objects
ApplicationModel
: include LinkedRails::Model
ApplicationController
: include LinkedRails::Controller
ApplicationSerializer
: include LinkedRails::Serializer
ApplicationPolicy
: include LinkedRails::Policy