Entregis is an app to connect customers with the carrier. By providing a service to create freight with items, the customer can find the either cheapest or closest carrier.
What is under this app? It's a basic Rails API. The data is serialized with active-model-serializer using JSON-API as adapter. The data are stored on Postgres, the postgis was enabled to store some geography/geometric data. The dry-rb is being used for dependency management system, data validation, operations, and data type definition.
Why I've chosen this kind of stack instead of another one.
At first, why Rails? Rails is such modular. Earning the active-record (ORM) I was able to include the activerecord-postgis-adapter to handle better geometric data types. The Rails give me more power to build a modular and flexibility application.
What about Active Model Serializer? I have used in all applications to serialize data. It's modular, easy configuration, and have support for JSON API.
What about JSON API? It's important to define application standards. I'd say the serializer is one sensitive part of the application system. Usually, it can have pagination, metadata, results... The JSON API has a specification for building APIs in JSON. That's great for the following reason: Is hard to define a standard, you can take a lot of time to define your response. JSON API has already done it. I can focus on what matters: the application.
What about Postgres? I was thinking about what kind of approach. So, I took my decision thinking about a real project. Thinking about costs and manageability. Postgres is a powerful database store. Writing and reading are extremely fast operation and easy to manage. I've chosen Postgres thinking mainly about costs and manageability.
What about Dry-rb? Rails is simple, based on MVC architecture. The problem of this approach is business logic belongs in models, it works well for small applications, but they grow and can find business logic spread. It's hard to follow DRY principle. The dry-rb offers to developers an ecosystem of gems that could help build healthy architecture. I'm using some essentials features/plugins of, such as: dry-matcher
, dry-monad
and dry-container
.
Basically, dry-matcher
offers a flexible, expressive pattern matching for Monad Result.
The dry-monad
is a set of common monads for Ruby. Monads provide an elegant way of handling errors, exceptions and chaining functions so that the code is much more understandable and has all the error handling, without all the ifs and else.
The dry-container
is a simple, thread-safe container, intended to be one half of a dependency injection system.
A board on Trello has been created for developing tracking and management.
Some most important missing features
- Adding
available_filters
into response's metadata - Support to relevant filter for the best carriers for a freight.
- Use other attributes to calculate the shipment cost. It would be great to support pricing by weight, fixed vehicle cost, distance in time.
- Idempotent endpoint. That's a really nice feature.
In order to run this app, you'll need Docker installed.
See the Docker website for installation instructions.
All endpoints were created and documented with Postman check out here.
We're using Heroku as PAAS for this app. The command git push heroku master
that's enough to deploy it.
This app is using a heroku manifest to define the app configuration. Thus, you can create your app from a "setup", just run the following commands below.
$ export APP_NAME='entregis'
$ heroku create $APP_NAME --manifest
$ docker-compose run --rm -e EDITOR=vi web rails credentials:edit && heroku config:set RAILS_MASTER_KEY=`cat config/master.key` -a $APP_NAME
$ heroku pg:psql -c 'create extension postgis;'
$ heroku run rails db:seed
We're using NewRelic as Monitoring APM.
We're using Rollbar as Tracking Error.
We're using docker-compose to increase the developing time. That's simple, check out the following code:
$ docker-compose build --pull
$ docker-compose run --rm web bundle exec rails db:setup
$ docker-compose up # (starting web server and database)
We're using pry-byebug
for debuggin'. Just put binding.pry
into the code and run the following code:
$ docker attach $(docker-compose ps -q web)
We're using Rubocop as linter. To lint the code just run:
$ docker-compose run --rm web bundle exec rubocop
This project is using RSpec on test suite.
At first, you must create the test database
$ docker-compose run --rm -e RAILS_ENV=test web bundle exec rails db:create db:migrate
$ docker-compose run --rm web bundle exec rspec