Jets is a Ruby framework which allows us to easily create and deploy serverless applications to AWS. Jets is adopting several concepts and patterns from Rails, which makes much easier the adoption of serverless architectures by Rails developers.
Jets is in early stages of maturity, however, its creator, Tung Nguyen, is making a lot of effort to improve the framework and the community around it is growing.
The application we'll be using as an example is the same previously used in Building AWS Lambdas for Real World using Ruby and Serverless Framework: a simple app which will consume data posted by Github. This sample project is available clicking here.
Like Leeroy Jenkins would say: Alright, time's up! Let's do this!
Prerequisites
Obviously, have Jets installed is necessary. If you don't have, go to your terminal and install it:
$ gem install jets
In order to deploy your app to AWS, you'll need to have your AWS keys set up in ~/.aws/credentials
. In case you don't have, please refer to Configuration and Credential files.
Creating our Jets app
Since we're not interested in assets serving, let's create our app using API mode:
$ jets new jetsapp --mode=api
$ cd jetsapp
By default, Jets supports ActiveRecord and DynamoDB via Dynomite. However, I'm interested in something different here: I want to use Dynamoid, which is a stable and mature Ruby ORM for AWS DynamoDB.
That said, let's update our Gemfile to add Dynamoid and remove mysql2.
# gem "mysql2", "~> 0.5.2"
gem 'dynamoid', '~> 3.1.0'
Don't forget to update your dependencies by executing bundle install
in your terminal.
Dynamoid requires AWS credentials in order to properly connect to DynamoDB. If we were in Rails, we could easily do it using initializers. Fortunately, initializers are one of the cool stuff adopted by Jets from Rails.
So, we just need to create config/initializers/dynamoid.rb
and add the following:
We're configuring the namespace
, which is optional (default is dynamoid
) and it's a prefix for our DynamoDB tables. We're also setting our AWS access key id, secret key and region. Obviously, we're keeping all these data in our environment variables.
Last but not least, we're creating DynamoDB tables based on the models we have in app/models
. Don't worry about the recreation of these tables when you perform a redeploy: Dynamoid takes care of it.
Now, let's update our .env
file:
ACCESS_KEY_ID=<your_access_key_id>
SECRET_ACCESS_KEY=<your_secret_access_key>
REGION=<region>
Important: while writing this article, I figured out that are some environment variable names reserved by AWS, for instance, AWS_REGION
. So take care to not use them :D
Models
Let's continue updating the app/models/application_item.rb
, which is intended to be the parent class of all DynamoDB models. The default ApplicationItem
generated by Jets looks like this:
Since we're not using Dynomite
, we can remove it and include the Dynamoid::Document
.
After that, let's build our GithubEvent
model.
As you can see, we're defining the table name, fields names and types (the default is string
), as well as some validation rules. Dynamoid automatically creates three fields: id
(string), created_at
(datetime) and updated_at
(datetime).
Dynamoid also allows use to use: default field values, custom field types, associations, validations, callbacks, STI (Single Table Inheritance), record creation, querying and much more.
Controller
Using Jets, we can create a simple lambda function, or we can build our controller and each action will be transformed into an AWS lambda function. Let's use the second approach just because we can!
The github
action will be responsible for receiving Github events data. The implementation couldn't be simpler! As you can see, even though we're not implementing a lambda function (which has the event
and context
arguments), the event
variable is available. Btw, params
is also available!
Finishing
Let's add the route to our config/routes.rb
file:
And finally, execute jets deploy
in our terminal to deploy our application. If you don't want to use the default profile to deploy, simply execute AWS_PROFILE=<profile_name> jets deploy
.
Final considerations
I really like the idea of Jets framework: to bring concepts and patterns from Rails world to make our lives easier while migrating to serverless. Although the framework is still not mature for critical applications, I will definitely give it a try.
Special thanks to Tung Nguyen for the awesome support!
Looking for a job?
If you're looking for a job and are willing to relocate to Frankfurt (Germany), consider to take a look on the positions available at creditshelf.
Top comments (5)
Thanks for posting this! I've been interested in Jets since I heard about it and I'm going to try something out on it this week. I'll be sure to reference your post about it.
Can I ask why you wanted to use Dynamoid instead of Dynomite?
Hi Phil!
I'm glad you like it! Well, basically because Dynomite looks to be in early stages of development, and Dynamoid also offers more interesting features, like associations, validations, callbacks, etc.
Ah, makes sense. I hadn't heard of either of them before. Thanks!
Thanks for this!
I am curious to know if you would be able to run tests using mini-test with this?
i tried but i was getting some errors because rails would try to connect to sqlite3 instead of Dynamodb.
Hello Serverless combines the power of Jets and Dynamoid to create efficient, scalable applications. Jets simplifies serverless Ruby development, while Dynamoid serves as a robust DynamoDB ORM, streamlining database interactions. Together, they enable developers to build applications that are both responsive and cost-effective. For more insights on leveraging serverless architecture, visit zelajet.com for valuable resources and tutorials!