At OmbuLabs, we recently had the opportunity to develop a Discord bot from scratch. We found the experience both rewarding and insightful, prompting us to create this tutorial to share our approach with you.
In this guide, we’ll walk you through the process of creating a Discord bot using Ruby on Rails, leveraging the efficiency and ease of development provided by this powerful framework.
Configuring your Rails application can be tricky. How do you define secrets? How do you set different values for your local development and for production? How can you make it more maintainable and easy to use?
Using environment variables to store information in the environment itself is one of the most used techniques to address some of these issues. However, if not done properly, the developer experience can deteriorate over time, making it difficult to onboard new team members. Security vulnerabilities can even be introduced if secrets are not handled with care.
In this article, we’ll talk about a few tools that we like to use at OmbuLabs and ideas to help you manage your environment variables efficiently.
When working with complex forms, it’s really easy to immediately start adding JavaScript to implement non-common behaviors. But there are some hidden gems in the HTML standard that allow us to do a lot of that without adding a single line of JavaScript!
Email threads are great for improving the user experience of your app. In this post we
will learn how the RFC 5322 specification expects us to thread emails. We will also learn
that emails don’t always work as we expect them to. At the end of this post you will have
email threading as another tool in your Rails belt.
With the release of Rails 6, Webpack was introduced as the default JavaScript bundler by using the Webpacker gem. We tend to think about Webpack only as a tool to handle JavaScript files, but it can be used to handle all kinds of asset files. This article shows how to create a Rails app that uses only Webpack to handle all the assets, including images, fonts, styles and videos.
Rails UJS (Unobtrusive JavaScript) is the JavaScript library that helps Rails do its magic when we use options like remote: true for many of the html helpers.
In this article I’ll try to explain the main concept of how this works to make it transparent for the user. Knowing a bit about the inner workings can help when debugging issues and also if we need to do something more complex than the provided interactions but reusing what’s provided.
If you are using an old version of Rails and you are still using jquery-ujs, some code will not reflect how it does the magic, but most of these concepts apply as well (rails-ujs is a re-implementation of jquery-ujs removing the jquery dependency).
Previously, I outlined the new hotness that is Hotwire. New features are nice, but what can you build with it? Let’s build a little project, and let’s make it something different from the usual Twitter clone that’s being used to demonstrate this new feature. Instead, I’ll show how to build a basic scrolling price ticker like you’d see on any stock site that updates in real time. We’ll learn a few interesting things along the way.
Have you ever had to deal with complex forms creating multiple objects and hierarchies in one request? Rails is there to help provide a set of helpers, methods and conventions to build nested forms, handle assignment, and creation of the objects involved in only a few lines of code. In this blog I’ll explain how that works using accepts_nested_attributes_for, fields_for, strong parameters and more.
One of the most visible and controversial new developments with the release of Rails 6.0 is Hotwire. Like anything in web development, the growing popularity of single page applications using JS frameworks has sparked some resistance. Arguably, the duplication of logic that single page applications often require violates the DRY principle. There are also many developers who would like the responsiveness of single page applications without all of the client side JavaScript and it’s associated headaches. There are a considerable number of developers who’d like the pendulum to swing back towards the server, but maybe keep some of the more desirable aspects of the SPA pattern. Hotwire is a fresh take on how to do this the Rails way.
Devise is a well known solution for authentication in Rails applications. It’s full featured (it not only adds authentication but also password recovery, email changing, session timeout, locking, ip tracking, etc.) and can be expanded to add even more (like JWT authentication).
In this post, I’ll go over the code related to the basic database authentication process, how it relates to Warden and some of the magic behind it. If you don’t know what Warden is, I will be explaining the role it plays for Devise in this article.
Since the release of Rails 6, Webpack is the default JavaScript bundler for new Rails apps. We all struggled at first coming from a Sprockets background, and more often than not, we, as Rails developers, tried to avoid making JavaScript changes so we wouldn’t have to deal with it.
In this post, I’ll try to explain some basic concepts and ideas from the point of view of a Rails developer used to working with the Assets Pipeline, comparing how to do the same thing on both.
We, Ruby developers, are used to running scripts or commands with the prefix bundle exec, but sometimes it’s not needed, but sometimes it is, and when it’s not needed it still works just fine if we add it. So it may not be clear why we need to use it in some cases.
In this blogpost I’ll try to answer these questions with a little insight on what Bundler (and Ruby and Rubygems) do.
In the first and second parts of this series we talked about positional and keyword arguments, but we still have some extra options so that our methods can do anything we want.
In this final part we are going to explore blocks, array decomposition, partially applied methods and a few syntax tricks. We’ll also study a few known methods to understand how everything is used in real world applications.
In the first part of this series we talked about positional arguments, but there are more types. In this second part we’ll talk about keyword arguments.
Positional and keyword arguments share a lot of characteristics so we’ll split this article into similar sections, but there are some key differences we’ll touch on in each section.
Ruby is an object oriented language where everything is an object (even methods are objects of the class Method!), so everything we need to do is done by calling methods on objects. That also means that methods have to provide a lot of flexibility because they are used everywhere.
Ruby provides a lot of options to pass arguments to our methods, so we’ll make this topic a series so it’s not too long. We’ll split the options into different categories and then break down everything with some examples and/or use cases.
Here at OmbuLabs, we do a lot of work with older versions of Ruby and Rails. Recently, I’ve been taking a look at Docker, the virtual container platform, to see how it might help us manage the often idiosyncratic setup that applications we work with might require.
At OmbuLabs we use Jekyll to generate our blog. If you are not familiar with it, here is a quick description from the Jekyll site:
“Jekyll is a simple, extendable, static site generator. You give it text written in your favorite markup language and it churns through layouts to create a static website. Throughout that process you can tweak how you want the site URLs to look, what data gets displayed in the layout, and more.”
Some time ago we wrote an article to explain how to implement Stripe Connect in a Rails application. That article covered mainly the connection part between Rails and Stripe. This one will cover the fun part, which is making transactions, charges, refunds, and more.
If you haven’t checked out the first part yet I recommend you do so since this article will continue from where that one ended.
Service Objects are a controversial idea for several different reasons: some developers like to use them, others like to use similar patterns, and some think that they are just unnecessary because they prefer fat models.
Here at OmbuLabs we like to use service objects whenever we can, we think it’s a great way to keep our controllers skinny.
In this post I would like to discuss my idea about service objects and why it’s adopted by our team.
In a recent project for OmbuLabs, we had to integrate Bitrix24 (the tool that the client was using to administrate their business) with the Rails application that we were building for a client.
The goal of this integration was to sync data between the Rails app and the Bitrix CRM. Basically we wanted to pull data from Bitrix every time there was a change (i.e. Lead was created/updated). We also wanted to sync the other way around, push changes to Bitrix every time something changed on the Rails side.
Everyone has had the experience of working on a gnarly, difficult to
understand code-base. The sort of code base that makes you hate your
job. Often it comes down to poor design, but code
conventions also
play a large part in whether you wake up dreading your job in the
morning. The overall design (choice of design patterns and how
modules and classes are organized and factored) is the long range, big
picture strategy of how an application will be made. Code
conventions, by contrast, come down to the choices you make about
which constructs of a language you use, which you don’t, and when.
In a previous article we talked about one of the Rails Girls events that we sponsored and co-organized in 2018. Fast forward one year to our first event of 2019 at A3, a new coworking space located in Buenos Aires, we were once again sponsors and volunteers at another successful Rails Girls event.
Sidekiq Pro comes with a great feature to process a collection of jobs as a batch, allowing them to be monitored as a group and executing a callback function when all the jobs are finished. This is useful when you need to load a lot of spreadsheet files into your database.
Recently, that was the case of one of OmbuLabs’ clients. They needed to upload a CSV file with over 10 thousand rows of loans data, which makes processing the file synchronously impossible because the browser will time out after a few seconds. Breaking the file into smaller ones wasn’t a good idea either, because it would take an unacceptable amount of time to finish. So we decided to use the Sidekiq’s batch logic.
Since Sidekiq Pro wasn’t an option at the time, we had the challenge of implementing the same pattern that Sidekiq Pro uses in their Batches processing. This article will show how we did it.
One of the first complications that most webapps of any complexity will run into is the need for privileged users who can do things that normal users can’t or shouldn’t be able to do. Before too long, you’re headed towards writing your very own administrative interface. This is not only extra work, but can be tricky to do without compromising the security of the application you’re administering. Most Rails developers will be familiar with this story, and Rails being Rails, it turns out that there are a couple of good options for extending your existing applications with a pre-generated, customizable admin console.
When it comes to database migrations the policy of Rails is very clear. It’s all
about altering the database structure with gradual migration files:
“Migrations are a convenient way to alter your database schema over time in a
consistent and easy way.” (source)
But, what about data migrations? What’s the best way to write, maintain, and run
migrations that alter the data in your production database?
In this article I will talk about three different patterns for writing and
maintaining your data migrations:
If you’re looking for services that handle the delivery of your emails and SMSs in your app, SendGrid and Twilio are some of the most complete options out there.
In this article we are going to focus on a common scenario when using those services: How can we have a real time status of the emails and text messages that we send from our Rails app.
When Nate announced a series of public workshops I
didn’t hesitate and signed up as quickly as possible. Here are my notes from my
experience at the workshop on October 17th.
The internet is a wonderful place, but there will always be people that don’t have good intentions when they visit our websites. That’s why you need to be aware of the vulnerabilities that your application can have and how to avoid them. In this article I’ll cover two common security problems in Rails applications (I’ll probably make a second part since this is a very extensive topic).
Hello and welcome to the first OmbuCast by OmbuLabs. In this screencast we’ll
be taking a look at the
derailed_benchmarks gem,
and how you can use it to benchmark your Rails application and find, and
hopefully fix bottlenecks in your code.
If you live in Argentina and you ever use AFIP, you should already know that their platform is not the best in terms of user friendliness.
We wanted to integrate OmbuShop with AFIP (using their API) in order to generate and print the bills for each seller. Unfortunately, there is no way to do this because the API doesn’t generate a printable version (PDF) of the bill.
How many times did you come across a great gem you wanted to try out in
a production console, like benchmark-ips
or awesome-print?
Be it for performance or for readability, sometimes it’s nice to be able to try
out something new quickly without going through a pull request + deployment
process. This is possible by modifying the $LOAD_PATH
Ruby global variable and requiring the gem manually.
When working on a Rails project, you may have seen present? calls on
ActiveRecord relationships. This might feel natural, mostly because present?
exists on all objects via ActiveSupport, so you expect the relationship to respond to it,
but it’s actually not a very good idea. If all we want to do is check if the
scope returns any results from the database, there are better ways than using
present?.
A few weeks ago, I noticed weird output in the RSpec
test suite (~4000 tests) for a Rails application:
.............................................................................................unknown OID 353414: failed to recognize type of '<field>'. It will be treated as String ...........................................................................................................................................
This Rails app uses a PostgreSQL database. After
some Googling, it turns out that this is a warning from PostgreSQL. When the
database doesn’t recognize the type to use for a column, it casts to string by
default.
When writing tests for services, you may sometimes want to use mock objects
instead of real objects. In case you’re using ActiveRecord and real
objects, your tests may hit the database and slow down your suite. The
latest release of the rspec-mocks
library bundled with RSpec 3 includes at least three
different ways to implement a mock object.
Let’s discuss some of the differences between a spy, a double and an
instance_double. First, the spy:
A few times in the past I’ve had to interact with IMAP via Ruby, and wrapping
your head around its API is not so easy. Not only is the IMAP API
a bit obscure and cryptic, but Ruby’s IMAP documentation
is not so great either.
Searching the internet for examples doesn’t yield too many results, so I’ll try
to write down some of the things I’ve learned. The examples I’ll show use
Gmail as the target IMAP server.
I’m a big fan of having small classes. I’m not a big fan of having huge specs for
a small class/object. Every time I see an opportunity to
DRY my specs, I take it.
Today I wrote a spec to make sure that we gracefully ignore SPAMmy
contact requests in the OmbuLabs
contact page. It initially looked like this:
test"gracefully ignores spammy requests with valid attributes"do@valid_contact=contacts(:two)attributes=@valid_contact.attributes.merge(email_confirmation: @valid_contact.email)assert_no_difference("Contact.count")dopost:create,contact: attributes,format: 'js'endassert_response:successend
The new behavior adds a simple SPAM trap field
that bots will usually fall for.
If a bot is submitting the email_confirmation field (which is hidden by a CSS
class), then it is SPAM and it gracefully ignores the request.
Sessions provide you a nice little data storage feature where the application does not need to get the information directly from the database. So you do not have to persist data in your database and can easily store info about the user on the fly. This is a nice way to enhance the user experience on your page.
Let’s say that you want to show some users a new fancy sign up form and the rest the old form. If you store the version of the sign up form in a session variable, you don’t need to persist this info in your database.
Recently, we started using Skylight in production
for one of our clients’ Rails applications, in an attempt to try to improve the
performance of some of the more critical API endpoints.
Skylight reports on:
Time taken per request
Breakdown of time taken per SQL query
Object allocations per request
I noticed an unusually large amount of allocated objects for one request:
This request would take anywhere from 400ms to 3000ms to respond, which is
WAY too long.
Maybe in the past you stumbled over the two different approaches to setup your test variables. One way is the more programmatical approach by using instance variables, usually initialized in a before block.
When integrating Backbone.js in your Rails App, you might face the problem of the inability to verify the CSRF-Token.
The CSRF Protection secures your app with a token. Rails makes sure that the person who is interacting with your app is someone who started a session in your site, not some random attacker from another site. So you should not turn it off, unless you know what you are doing.
default_scope is a method provided by ActiveRecord, which allows you to set
a default scope (as its name implies) for all operations done on a given model.
It can be useful for allowing soft-deletion in your models, by having a
deleted_on column on your model and setting the default scope to
deleted_on: nil
Often, Enumerable#select is the chosen method to obtain elements from an
Array for a given block. Without thinking twice, we may be doing more work than
necessary by not taking advantage of another method from the Enumerable module,
Enumerable#grep.