In Rubyroid Labs we are very passionate about application architecture. Most projects we work here are long-term projects, so if you are not being careful about your application design at some point you will find yourself in a position where in order to add a new feature it’s just easier to rebuild the whole project from the scratch. And it’s definitely not something you want to face up with.
One of the bad signs that your project is getting sick is that new team members spend a significant amount of time just reading through the source code in order to understand the logic. Today we want share a list of different gems, which in our opinion can help you to organize your code and make your team members smile.
1. interactor
This library is absolutely fabulous and has always been in our shortlist when talking about writing some complex business logic. What is an interactor? As gem readme says – “an interactor is a simple, single-purpose object, used to encapsulate your application’s business logic”. You can think of that as a service-objects we all love, but it’s a way more than that. Let’s take a look on the example:
# app/interactors/create_order.rb
class CreateOrder
include Interactor
def call
order = Order.create(order_params)
if order.persisted?
context.order = order
else
context.fail!
end
end
def rollback
context.order.destroy
end
end
# app/interactors/place_order.rb
class PlaceOrder
include Interactor::Organizer
organize CreateOrder, ChargeCard, SendThankYou
end
In this example you probably noticed couple absolutely great features of this gem.
The first thing is that you are able to organize your simple interactors to an executable chain, which will be executed in proper order. Special variable context is being used to share states between different interactors.
The second thing is that if one of the interactors fails for some reason, all previous will be rolled-back. You could see that rollback on CreateOrder, which will drop an order if ChargeCard or SendThankYou fails.
It is so cool, isn’t it?
2. draper
If you have ever used custom Rails-helpers, you know how messy they become overtime. And in most cases we use them to display some data in a more fancy way. That’s where decorator design pattern can help us. Let’s take a look at a draper syntax, which is pretty self-explanatory:
# app/controllers/articles_controller.rb
def show
@article = Article.find(params[:id]).decorate
end
# app/decorators/article_decorator.rb
class ArticleDecorator < Draper::Decorator
delegate_all
def publication_status
if published?
"Published at #{published_at}"
else
"Unpublished"
end
end
def published_at
object.published_at.strftime("%A, %B %e")
end
end
# app/views/articles/show.html.erb
<%= @article.publication_status %>
In the code above you can see that our goal was to show published_at attribute in specific format. In classical rails-way we have 2 options of how to do that.
First one is just to write a special helper. The problem with this is that all helpers live under the namespace and as project longs you can face up with some weird name collision, which is extremely hard to debug.
The second one is to create a new method inside the model and use that method instead. This solution also feels wrong since it breaks model class responsibility. By default models are responsible for interaction with data, other than representation of that data.
That’s why using draper in this scenario is a more elegant way to achieve our goal.
Be sure that you check another stunning article:
19 Ruby on Rails Gems which Can Amaze
3. virtus
Sometimes using a simple ruby object is not enough for you. Imagine you have some complex form on a page, where different pieces form should be saved as different models in the database. That’s where virtus can help you. Let’s take a look at the example:
class User
include Virtus.model
attribute :name, String
attribute :age, Integer
attribute :birthday, DateTime
end
user = User.new(:name => 'Piotr', :age => 31)
user.attributes # => { :name => "Piotr", :age => 31, :birthday => nil }
user.name # => "Piotr"
user.age = '31' # => 31
user.age.class # => Fixnum
user.birthday = 'November 18th, 1983' # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
# mass-assignment
user.attributes = { :name => 'Jane', :age => 21 }
user.name # => "Jane"
user.age # => 21
As you can see, virtus looks similar to standard {OpenStruct} class, but gives you many more features. You should definitely play around to explore them all.
This gem could be a good start for you, but if you are looking for more advanced techniques – definitely go and check dry-types, dry-struct and dry-validation.
4. cells
If you are not familiar with Nick Sutterer Ruby on Rails advanced architecture, you should definitely check that out. Not all of us ready to apply this whole concept to their existing applications. But sometimes your views become really complicated, with different conditions applied for different types of user and etc. That’s where cells gem could help. It allows moving part of you views to isolated components, which are just regular ruby-classes. Let’s take a look at code sample:
# app/cells/comment_cell.rb
class CommentCell < Cell::ViewModel
property :body
property :author
def show
render
end
private
def author_link
link_to "#{author.email}", author
end
end
# app/cells/comment/show.html.erb
<h3>New Comment</h3>
<%= body %>
By <%= author_link %>
# app/controllers/dashboard_controller.rb
class DashboardController < ApplicationController
def index
@comments = Comment.recent
end
end
# app/controllers/dashboard/index.html.erb
<% @comments.each do |comment| %>
<%= cell(:comment, comment) %>
<% end %>
In this example we want to display recent comments on our dashboard. Imagine all comments should be displayed identical on our application. Rails will use some shared partial for rendering. But instead of doing that we use CommentCell object. You can think of that object as a combination of draper we talked about before with ability to render views. But of course it has many more features. Check their README to learn more about all options.
How to Clear Out Your Controllers and Models With Waterfall Gem
5. retryable
All modern web application do have different types of integrations. Sometimes it’s made through solid API calls, sometimes you have to upload a file to FTP or even use some binary protocol. Problem with all integrations is that sometimes their calls just fail. In some cases – it fails without any reasons. And the best thing you can do is just to try again. Thumbs up if you have ever had to do something like this:
begin result = YetAnotherApi::Client.get_info(params) rescue YetAnotherApi::Exception => e retries ||= 0 retries += 1 raise e if retries > 5 retry end
Here is where retryable can help you. Let’s take a look at how we can rewrite the example above using that gem:
Retryable.retryable(tries: 5, on: => YetAnotherApi::Exception) do result = YetAnotherApi::Client.get_info(params) end
It looks much nicer, doesn’t it? Check that gem out for other scenarios it supports.
6. decent_exposure
If you are not a big fan of using magic – this library is not for you. But in some applications we definitely have a lot of duplications for very simple and standard CRUD actions. That’s where decent_exposure could help you. Let’s imagine that we are creating new controllers to manage things. That’s how scaffold will look for us:
class ThingsController < ApplicationController
before_action :set_thing, only: [:show, :edit, :update, :destroy]
def index
@things = Thing.all
end
def show
end
def new
@thing = Thing.new
end
def edit
end
def create
@thing = Thing.new(thing_params)
respond_to do |format|
if @thing.save
format.html { redirect_to @thing, notice: 'Thing was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if @thing.update(thing_params)
format.html { redirect_to @thing, notice: 'Thing was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
@thing.destroy
respond_to do |format|
format.html { redirect_to things_url, notice: 'Thing was successfully destroyed.' }
end
end
private
def set_thing
@thing = Thing.find(params[:id])
end
def thing_params
params.require(:thing).permit(:for, :bar)
end
end
We can’t say that 60 lines of code is not too much. But as rubyists we always want it to be as minimalistic as possible. Let’s take a look at how it could be transformed using decent_exposure:
class ThingsController < ApplicationController
expose :things, ->{ Thing.all }
expose :thing
def create
if thing.save
redirect_to thing_path(thing)
else
render :new
end
end
def update
if thing.update(thing_params)
redirect_to thing_path(thing)
else
render :edit
end
end
def destroy
thing.destroy
redirect_to things_path
end
private
def thing_params
params.require(:thing).permit(:foo, :bar)
end
end
Yakes! Now it’s a little more than 30 lines of code without losing any functionality. As you could notice – all magic is brought by expose method. Check this gem documentation for a better understanding of how things work under the hood.
7. groupdate
Every developer knows that dealing with different time zones is a hard thing. Especially when you are trying to write some aggregation on your database. It always gave me hard time when someone asked: “Could I get how many users we are getting every day this month excluding free users” or similar. Now you can stop worrying about such requests and just use gem. Here is an example:
User.paid.group_by_week(:created_at, time_zone: "Pacific Time (US & Canada)").count
# {
# Sun, 06 Mar 2016 => 70,
# Sun, 13 Mar 2016 => 54,
# Sun, 20 Mar 2016 => 80
# }
Hope you enjoyed some of these libraries. Let us know if you have any other tools in your mind which can help to write more expressive and awesome code.

2 Comments
Thanks! Great article!
Thanks, Radoslav!