The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or clickhereto continue anyway

Announcing Lotus v0.3.1

Announcing Lotus v0.3.1

Posted by Luca Guidi on May 15, 2015

Lotus patch release: RESTful nested resource(s), dirty tracking and timestamps for entities, improved code generators, bug fixes.


This patch release ships new features and improved code generators.

RESTful nested resource(s)

RESTful resource(s) can be nested with infinite levels.

# apps/web/config/routes.rb resources :users do resource :avatar resources :events end

This generates the following routes:

% lotus routes new_user_avatar GET, HEAD /users/:user_id/avatar/new user_avatar POST /users/:user_id/avatar user_avatar GET, HEAD /users/:user_id/avatar edit_user_avatar GET, HEAD /users/:user_id/avatar/edit user_avatar PATCH /users/:user_id/avatar user_avatar DELETE /users/:user_id/avatar user_events GET, HEAD /users/:user_id/events new_user_event GET, HEAD /users/:user_id/events/new user_events POST /users/:user_id/events user_event GET, HEAD /users/:user_id/events/:id edit_user_event GET, HEAD /users/:user_id/events/:id/edit user_event PATCH /users/:user_id/events/:id user_event DELETE /users/:user_id/events/:id users GET, HEAD /users new_user GET, HEAD /users/new users POST /users user GET, HEAD /users/:id edit_user GET, HEAD /users/:id/edit user PATCH /users/:id user DELETE /users/:id

The corresponding endpoints are actions like Web::Controllers::Users::Avatar::Create or Web::Controllers::Users::Events::Show.

Dirty Tracking

Entities can now track changed attributes and dirty status.

# lib/bookshelf/entities/user.rb class User include Lotus::Entity include Lotus::Entity::DirtyTracking attributes :name, :age end

This new feature is activated by including Lotus::Entity::DirtyTracking. It exposes #changed? and #changed_attributes.

# Usage user = 'L') user.changed? # => false user.age = 33 user.changed? # => true user.changed_attributes # => {:age=>33} user = UserRepository.create(user) user.changed? # => false user.update(name: 'Luca') user.changed? # => true user.changed_attributes # => {:name=>"Luca"} user = UserRepository.update(user) user.changed? # => false result = UserRepository.find( result.changed? # => false

When an entity is initialized and after it’s created or updated, the state is clean. If we mutate the state with an assigment or with Entity#update, #changed? returns true.


If an entity has :created_at and/or :updated_at attributes, when it’s persisted, the repository will take care of manage these values for us.

# lib/bookshelf/entities/user.rb class User include Lotus::Entity attributes :name, :created_at, :updated_at end

We have mapped both these attributes as DateTime.

user = 'L') puts user.created_at # => nil puts user.updated_at # => nil user = UserRepository.create(user) puts user.created_at.to_s # => "2015-05-15T10:12:20+00:00" puts user.updated_at.to_s # => "2015-05-15T10:12:20+00:00" = "Luca" user = UserRepository.update(user) puts user.created_at.to_s # => "2015-05-15T10:12:20+00:00" puts user.updated_at.to_s # => "2015-05-15T10:12:23+00:00"

Application Generator

Lotus default architecture is named Container, as it allows to run multiple Lotus (and Rack) applications within the same Ruby process.

When we generate a new project with lotus new bookshelf, it creates a default application named Web, under apps/web. This architecture enforces a separation between components and it will make our life easier if we want extract microservices at a later stage.

If we want to introduce a new component in our container (eg. an admin pane, a metrics dashboard), we can use the new application generator.

lotus generate app admin

This command will add a new application named Admin under apps/admin, and it will be available under the /admin URL namespace.

Model Generator

This last feature is really helpful while developing our domain model. It generates an entity, a repository and the related test files.

% lotus generate model user create lib/bookshelf/entities/user.rb create lib/bookshelf/repositories/user_repository.rb create spec/bookshelf/entities/user_spec.rb create spec/bookshelf/repositories/user_repository_spec.rb

What’s Next

New features such as migrations, form helpers and improved security are under development right now. We’re pushing to ship soon.

Continue reading on