Never miss an update:

  • Exploring the Simple Form Gem

    During my first months at Springest, as a fast-learning junior developer, I will be diving into the workings and usage of popular gems and posting here my experiences with each of them once in a while. Simple Form is the gem of this week!

    Forms are essential for user input in web applications. However, they can become tedious to write and maintain because of the need to handle form control naming and its numerous attributes.

    That’s where the Simple Form gem comes in handy. It aims to be as flexible as possible while helping you with powerful components to create your forms. And don’t worry, because you will still be able to define your layout the way you do now.

    What We Are Building

    In this article we will be building a model-centric form for creating and editing companies including the following fields: a text field for its name, a text area for its description, a select box for its size (number of employees) and a checkboxes collection for its different categories.

    Defining Relationships Between Models

    To be able to build this form we will first need a company and a category models. Beside these two models we will also have a characterization join model, which will be in charge of connecting the company and the category models. Any particular row in the characterizations table will effectively join a row in the companies table and a row in the categories table.

    Check out the following diagram showing the models associations:

    The following code shows the corresponding validations and how the structure would look like:

    class Company < ActiveRecord::Base
      has_many :characterizations, dependent: :destroy
      has_many :categories, through: :characterizations
      SIZES = ["0-10", "11-30", "31-50", "More than 50"]
      validates :name, presence: true, uniqueness: true
      validates :description, presence: true
      validates :size, presence: true, inclusion: { in: SIZES }
    class Category < ActiveRecord::Base
      has_many :characterizations, dependent: :destroy
      has_many :companies, through: :characterizations
      validates :name, presence: true, uniqueness: true
    class Characterization < ActiveRecord::Base
      belongs_to :company
      belongs_to :category

    Let’s Build the Form

    I will be guiding you through the different form helpers in Simple Form and how to use them compared to the built-in Rails Form Builder.

    The form will be scoped to the company model and to start using Simple Form you just have to add the helper it provides:

    <%= simple_form_for @company do |f| %>

    Adding a Text Field and a Text Area

    When using the Rails Form Builder you need to specify one by one the type for each of the different form helpers and add a corresponding label to them. For the text and the text area fields you then have to pass in the name of the attribute to be called on the company object (name and description in this case).

    <%= f.label :name %>
    <%= f.text_field :name %>
    <%= f.label :description %>
    <%= f.text_area :description %>

    One of the nicest things about Simple Form is that you don’t need to specify the type of the different form elements, but it will figure that out by itself looking at the column type in the database and use an appropriate input for the column. For example, a column created with type :text in the database (like the company’s description in our case) will use a textarea input by default. You can check here a complete list of the available input types and defaults for each column type.

    A label element will also be added by default to each of the fields, transforming the above code into this:

    <%= f.input :name %>
    <%= f.input :description %>

    Adding a Select Box

    In the case of a select box, Rails Form Builder will also need the options array to be passed in as a second parameter.

    <%= f.label :size %>
    <%= :size, Company::SIZES %>

    With Simple Form if you want to create a select containing the different sizes of a company you can do it overriding the :collection option. Collections can be arrays or ranges, and when a :collection is given the :select input will be rendered by default, so no need to pass the as: :select option:

    <%= f.input :size, collection: Company::SIZES, prompt: "- Select number of employees" %>

    Adding a Checkboxes Collection

    To generate a collection of checkboxes with Rails Form Builder we will need to pass in the following parameters to the form helper:

    • Name of the attribute or method to be called on the company object (as in the previous form elements)
    • Options array or collection to be shown
    • Name of the attribute to be used as the checkbox value
    • Name of the attribute to be used as the checkbox label text
    <%= f.label :categories %><br>
    <%= f.collection_check_boxes(:category_ids, Category.all, :id, :name) %>

    To deal with these type of associations, Simple Form can generate either select inputs or a series of radios buttons or checkboxes. We will only need to pass in the categories collection as a parameter. The association helper would render a :select input by default, which can be changed into radio buttons or checkboxes like we did in this case:

    <%= f.association :categories, as: :check_boxes %>

    What We Got

    Our form will end up looking very short and simple indeed ☺ :

    <%= simple_form_for @company do |f| %>
      <%= f.input :name %>
      <%= f.input :description %>
      <%= f.input :size, collection: Company::SIZES, prompt: "- Select number of employees" %>
      <%= f.association :categories, as: :check_boxes %>
      <%= f.button :submit %>
    <% end %>

    What’s Next

    If you didn’t have enough and you are actually interested in doing more complicated things with Simple Form, you will be happy to hear that:

    Read more
  • Running a Rails application on AWS using Elastic Beanstalk and Docker

    Deploying to AWS or any other server environment can be a chore. Fortunately there are tools like Elastic Beanstalk and Docker to make life a little easier.

    Elastic Beanstalk

    Elastic Beanstalk offers a lot of bang for your buck. Deployment, auto scaling, load balancing and database management are just some of the features Elastic Beanstalk offers out-of-the-box.

    It’s hard to find a software platform that isn’t supported by Elastic Beanstalk, it currently offers support for Ruby, PHP, Python, Java, .NET, Node.JS and Go. But it doesn’t stop there, for every platform there is a multitude of platform versions and servers to run your application. Just for the Ruby environment you can choose between several versions of Ruby in combination with Passenger or Puma.

    But it doesn’t stop there! Elastic Beanstalk has one more trick up it’s sleeve: The ability to run your application inside a Docker container.

    Why Docker?

    There are a lot of advantages to using Docker for running your application. A very incomplete list:

    • Less overhead on the environment running your application.
    • Test and run your application in the same environment.
    • Easy to debug. You can export a faulty container, download it and start it locally.
    • Simplify configuration, less need for customising the host environment using .ebextensions.
    • Faster deployments and auto scaling.

    We had been experimenting with using Docker to run our stack for a while. Our first try was using Deis to run our staging environment. We saw a lot of potential and spent quite a lot of time on getting our stack to work but, in the end we simply didn’t feel comfortable with the level of stability Deis was offering.

    This made us little weary of trying it again on Elastic Beanstalk but, after some initial experimentation we were sold!

    If you are interested in knowing more about our experiences using Deis please let us know in the comments. If we receive enough interest we might devote an article to the subject.

    Our solution

    There’s more than one way to go about deploying an application on an Elastic Beanstalk Docker environment. First of all, you have the choice between running a single or multi-docker container setup. For our purpose the Single Docker setup works just fine.

    First, we are going to need a base docker image that we can use for our deployments:

    FROM springest/ruby:2.1.5
    RUN apt-get -y -q update && apt-get -y -q install build-essential python-dev python-pip && apt-get clean
    RUN pip install awscli awsebcli
    RUN echo 'gem: --no-ri --no-rdoc' > ~/.gemrc
    # Rubygems and bundler
    RUN gem update --system --no-ri --no-rdoc
    RUN gem install bundler --no-ri --no-rdoc
    RUN git config --global ""
    RUN git config --global "AwesomeApp"

    Build and push this to a Docker repository like Docker Hub or

    docker build -t awesome_app/base .
    docker tag awesome_app/base:latest awesome_app/base:0.1
    docker push awesome_app/base

    You should of course replace awesome_app with the name of your own organisation on the Docker repository.

    Next we will create the file. This file holds the configuration needed for Elastic Beanstalk to deploy your Docker container:

      "AWSEBDockerrunVersion": 1,
      "Ports": [
          "ContainerPort": "3000"
      "Volumes": [
          "HostDirectory": "/var/app/current/webapp/tmp",
          "ContainerDirectory": "/webapp/tmp"
      "Logging": "/webapp/log"

    The file includes the following sections:

    • AWSEBDockerrunVersion - Specifies the version number. 1 for single and 2 for multi.
    • Ports - Which ports to expose on the Docker container.
    • Volumes - Which volumes should be mounted from host to the Docker container.
    • Logging - Where to mount the host log directory to the docker container. The host log directory can be found here: /var/log/eb-docker/containers/eb-current-app.

    If you are already familiar with the structure of the you might notice we left out the Image section. The above Dockerfile will be used as a base for a Docker image that will be built during deployment by Elastic Beanstalk. For this we need to create a different Dockerfile which will be sent along with all other application files to Elastic Beanstalk during deployment.

    Create the following Dockerfile and place it in config/docker:

    FROM awesome_app/base:0.1
    ADD webapp /webapp/
    WORKDIR /webapp
    CMD bundle exec puma -C config/puma.rb
    EXPOSE 3000

    In this example we start the application by running puma but you could just as easily start any other application server.

    For the final step we will need to pull it all together. We will be deploying from inside the awesome-app/base:0.1 docker container. For this we will create a simple script called deploy inside the script directory:

    function check_environment_status {
      echo "Checking if $environment is not updating..."
      STATUS=`eb status $environment | grep Status | sed 's/^[ ]*Status: \(.*\)$/\1/'`
      if [ "$STATUS" = "Updating" ]; then
        echo "Environment $environment is updating. Aborting deploy."
        exit 1
    function deploy_to_environment {
      echo "Deploying to $environment..."
      git add --all .
      git commit -q -m "Deploying to ${environment}"
      eb deploy --nohang --quiet
    rm -rf $DEPLOY_DIR
    mkdir -p $DEPLOY_DIR/{webapp/public,.elasticbeanstalk}
    cd $DEPLOY_DIR
    cat > $DEPLOY_DIR/.elasticbeanstalk/config.yml <<- EBC
        environment: ${ENVIRONMENT_NAME}
      application_name: awesome-app
      default_ec2_keyname: awesomeappkey
      default_platform: Docker 1.5.0
      default_region: ${EC2_REGION}
      profile: null
      sc: git
    mkdir -p /root/.aws
    cat > /root/.aws/config <<- ACF
    output = json
    region = eu-central-1
    aws_access_key_id = $AWS_KEY
    aws_secret_access_key = $AWS_SECRET_KEY
    git init .
    check_environment_status ENVIRONMENT_NAME
    echo "Copying Elastic Beanstalk files..."
    cp -r $BASE_DIR/.ebextensions $DEPLOY_DIR
    cp -f $BASE_DIR/ $DEPLOY_DIR
    cp -f $BASE_DIR/config/docker/Dockerfile $DEPLOY_DIR
    echo "Copying application files..."
    cp $BASE_DIR/ $DEPLOY_DIR/webapp/
    cp $BASE_DIR/Gemfile $DEPLOY_DIR/webapp/
    cp $BASE_DIR/Gemfile.lock $DEPLOY_DIR/webapp/
    cp $BASE_DIR/Rakefile $DEPLOY_DIR/webapp/
    cp -r $BASE_DIR/.bundle $DEPLOY_DIR/webapp
    cp -r $BASE_DIR/app $DEPLOY_DIR/webapp
    cp -r $BASE_DIR/config $DEPLOY_DIR/webapp
    cp -r $BASE_DIR/db $DEPLOY_DIR/webapp
    cp -r $BASE_DIR/lib $DEPLOY_DIR/webapp
    cp -r $BASE_DIR/public/assets $DEPLOY_DIR/webapp/public
    cp -r $BASE_DIR/public/images $DEPLOY_DIR/webapp/public
    cp -r $BASE_DIR/script $DEPLOY_DIR/webapp
    # Run bundle install here so we don't have to on every application server
    cd $DEPLOY_DIR/webapp
    bundle install --deployment -j4 --retry=3
    cd $DEPLOY_DIR
    # Remove any .git directory from gems that are downloaded from a git repository
    find $DEPLOY_DIR/webapp/vendor/bundle -name ".git" -type d | xargs rm -rf
    deploy_to_environment ENVIRONMENT_NAME
    rm -rf $DEPLOY_DIR

    In the example the EC2 region has been hardcoded to eu-central-1 but this can be changed to the region of your liking.

    The script creates two files needed by the Elastic Beanstalk CLI to deploy your application:

    • .elasticbeanstalk/config.yml - This file specifies the target environment for deployment
    • /root/.aws/config - This file specifies the AWS credentials file needed for authentication

    For the script to work it will need two environment variables:

    • $AWS_KEY

    These can be generated from the IAM console in your AWS console.

    Don’t forget to make the script executable:

    chmod +x script/deploy

    Finally, let’s run the script. First we will need to start a new docker container based on the awesome-app/base:0.1 image:

    docker run --rm -it -v $PWD:/webapp awesome_app/base:0.1 /bin/bash

    If everything went as planned you should be logged into the docker container as root.

    To run the script we first have to cd to the /webapp directory so we can run the deploy script:

    cd /webapp
    AWS_KEY=FOO AWS_SECRET_KEY=BAR script/deploy

    When the script is finished your application is pushed to Elastic Beanstalk for propagation to your EC2 instances, shaving a lot of time on spinning up new EC2 instances during auto scaling.

    What’s next

    Even though running the deployment from your local machine works perfectly fine, it would be a lot more efficient to let your CI environment take care of this. At Springest we use Wercker and their Ewok infrastructure to run our specs and deploy script.

    This article won’t go into detail how Wercker can be used to make the process even more efficient. If you are interested in the details please leave a comment. If we receive enough interest we might devote an article about it in the future.

    Read more
  • Deploy Notifications to NewRelic, AppSignal, and Slack with Elastic Beanstalk

    Note: This project is no longer maintained by our team, but it’s still cool to learn from. If you would like to take it over, email us, or check out one of its maintained forks.

    Amazon’s Elastic Beanstalk is a very nice platform to easily host simple applications, while it also gives you enough tools to customise your environment for more complex setups. One simple customisation we made here at Springest is a script to push deploy notifications to NewRelic, AppSignal, and our development Slack channel.

    Example Script for Slack

    For argument’s sake, we are going to use the Slack script as an example. The other scripts you can find in our repo.

    Below is an example script to post to Slack. It takes a couple of arguments. Read the usage info for more details. Note that this was heavily inspired by the scripts from @apancutt’s deploy notification script.

    Create a Webhook Integration in Slack

    First off, you need to create a webhook integration in Slack. You can do so by clicking the name of the channel you’re in and select Add a service integration.

    add a Slack webhook integration

    Create a file in script/ with the code below and make it executable with chmod +x script/

    # File: ./script/
    # Notify the team through Slack that a deploy is done on Elastic
    # Beanstalk.
    # Source:
    # Credits:
    # Usage: script/ -a TESTAPP -c aws-notifications -w
    function usage {
        echo "AWS Elastic Beanstalk Deployment Notifications for Slack (v${version})"
        echo "Usage: -a <APP NAME> -c <SLACK CHANNEL> -k <API KEY> [options]"
        echo "Options:"
        echo "  -a  The name your the application in Elastic Beanstalk."
        echo "  -c  The channel to post to (without the hash)."
        echo "  -w  The webhook url to post to."
        echo "  -d  The name of the deployer (default: AWS Elastic Beanstalk)."
        echo "  -c  The icon to use (without the colons, default: package)."
        echo "  -e  Error if the HTTP request fails. Note that this will abort the deployment."
        echo "  -h  Displays this help message."
        echo "  -q  Quiet mode."
        echo "  -v  Display version information."
    function info {
        echo "[INFO] ${@}"
    function warn {
        echo "[WARN] ${@}"
    function error {
        echo "[ERROR] ${@}" >&2
        exit 1
    if [[ ${#} == 0 ]]; then
        exit 1
    while getopts "a:c:w:d:i:ehk:qv" option; do
        case "${option}" in
            a) app_name="${OPTARG}";;
            c) channel="${OPTARG}";;
            w) webhook_url="${OPTARG}";;
            d) deployer="${OPTARG}";;
            i) icon="${OPTARG}";;
            e) error_on_fail=1;;
            h) usage; exit;;
            q) verbose=0;;
            v) echo "Version ${version}"; exit;;
            *) echo; usage; exit 1;;
    if [[ -z "${app_name}" ]]; then
        error "The application name must be provided"
    if [[ -z "${channel}" ]]; then
        error "The channel must be provided"
    if [[ -z "${webhook_url}" ]]; then
        error "The webhook_url must be provided"
    if [[ -z "${deployer}" ]]; then
        deployer="AWS Elastic Beanstalk"
    if [[ -z "${icon}" ]]; then
    if [[ -f REVISION ]]; then
        app_version=$(cat REVISION)
        error "Unable to extract application version from source REVISION
    if [[ -z "${environment}" ]]; then
    if [[ ${verbose} == 1 ]]; then
        info "Application name: ${app_name}"
        info "Application version: ${app_version}"
        info "Application environment: ${environment}"
        info "Webhook URL: ${webhook_url}"
        info "Channel: ${channel}"
        info "Icon: ${icon}"
        info "Sending deployment notification..."
    http_response=$(curl -X POST -s -d "{\"channel\":\"#${channel}\",\"icon_emoji\":\":${icon}:\",\"text\":\"${app_name} was successfully deployed to ${environment} by ${deployer}\",\"username\":\"${deployer}\",\"attachments\":[{\"fallback\":\"${app_name} was successfully deployed to ${environment} by ${deployer}\",\"color\":\"#8eb573\",\"fields\":[{\"title\":\"Environment:\",\"value\":\"${environment}\",\"short\":false},{\"title\":\"Version:\",\"value\":\"${app_version}\"}]}]}" "${webhook_url}")
    http_status=$(echo "${http_response}" | head -n 1)
    echo "${http_status}" | grep -q "ok"
    if [[ ${?} == 0 ]]; then
        if [[ ${verbose} == 1 ]]; then
            info "Deployment notification successfully sent (${app_name} v${app_version})"
        msg="Failed to send deployment notification: ${http_status}"
        if [[ ${error_on_fail} == 1 ]]; then
            error "${msg}"
            warn "${msg}"

    When you try to use the script above, it will fail with a:

    ⇒  script/ -a TESTAPP -c aws-notifications -w
    [ERROR] Unable to extract application version from source REVISION

    So let’s fix that.

    Creating the REVISION file

    AppSignal and Newrelic need a revision for best results, so we’re going to create one. We don’t have access to the git history directly while we run these scripts on EB, so let’s make sure they get created while we have it.

    You can either (1) update the REVISION file before you deploy with eb deploy or (2) have your CI / deploy tool (we use Wercker) write and commit the file. Either way, this is the command to update the file:

    git rev-parse HEAD > REVISION

    Script sources

    You can find the above script, and the scripts for NewRelic and AppSignal in the repository we created for it. Let us know if you have any fixes or improvements!

    Running the scripts during deploys

    To run the script, you need to tell EB which command to run. Additionally, you’ll want to make sure that it only runs once per deploy, and not on every instance (no need to have 40 deploy messages if you have 40 instances running your web cluster ;)

    So we’re going to use container_commands for that. Create a file called .ebextensions/003_notifications.config and provide the following input:

    # NewRelic, AppSignal, and Slack deploy notifications
        command: "webapp/script/ -a ${NEWRELIC_APP_NAME} -k ${NEWRELIC_API_KEY}"
        leader_only: true
        ignoreErrors: true
        command: "webapp/script/ -a ${APPSIGNAL_APP_NAME} -k ${APPSIGNAL_PUSH_API_KEY}"
        leader_only: true
        ignoreErrors: true
        command: "webapp/script/ -a <APP_NAME> -w ${SLACK_WEBHOOK_URL} -c <CHANNEL> -i <EMOJI_ICON>"
        leader_only: true
        ignoreErrors: true

    Setting the necessary ENV vars on Elastic Beanstalk

    As you can see from the example above, we use a couple of environment variables to call these scripts. To set these you can just use the eb command line tool:



    If all goes well, you will see the notification in Slack:

    example notification on Slack


    Read more
  • How I Taught Myself to Code

    Back in 2002 I went to college and studied architecture. At that time pursuing a career in tech did not cross my mind.

    After graduating college I worked as an architect during 5 years and in different countries. During that time I saw how some of the projects I worked on were built, such as a community-centre in Belgium, an office building in China or a private house in Amsterdam.

    The similarities of Architecture and Software development

    I consider the latest from those projects to be a great example of Data Oriented Architecture (I did not know back then that this term was used somewhere else ☺). The clients, a young couple expecting a child, were closely involved in the design process, which allowed for comprehensive research and understanding of how they behave and use their daily spaces.

    The project started by collecting important data. To fully comprehend their behaviors and use of their living space each of them were asked to describe a perfect day in their ideal house. Using their stories we mapped their personal belongings (such as their cats toys, his large number of t-shirts or her great boots collection) and domestic rituals (shower towels, laundry clothes or kitchen cluttery). We asked the clients to place all of them on top of the floorplan specifying the location where they would be stored/used.

    For those who are curious, you can read more here about the project.

    Through this example you can see the surprising similarities between designing a house and a web application, in which client’s behaviors are only replaced by user’s flow.

    The Scary Decision to Quit My Job

    Those years were fun. But in the middle of it I started to date my husband. This is when things started to change. He is a programmer, although he is not into web development, but he works in the games industry. He is very passionate about what he does and that made me extremely curious.

    We started to have more and more conversations about programming, using weird words like arrays, methods, classes, inheritance… Until I was totally trapped and decided to give it a try.

    It was July 2013 when I did it. I quit my job as an architect. It was quite scary!

    Why I Didn’t Go Back to College

    Let’s go back to college. This was my first thought. I started to look for computer science universities searching some source of inspiration. I filled in the application form for one of them and ordered some of their books… But the moment I opened them I knew it. That was not for me.

    I wanted to work in the web industry. Back then I didn’t know yet if it would be in the front-end or back-end side. But anyway what I saw in those books did not have anything to do with it.

    At last I asked google, who gave me thousands and thousands of online resources to choose from. It was overwhelming and I did not know where to start. So I took the time to play around with most of them. Finally I decided to do it as follows.

    How Combining Online Learning Sources Helped Me Get There Faster

    I first went to Treehouse and joined one of their tracks. For those of you who are not that familiar with their website, if you visit them they have different tracks based on what you want to become. I chose to become a PHP developer, as they were the most wanted people in Germany, where I was living at that moment.

    But sometimes what I was learning at Treehouse was not enough. And that’s why I was regularly complementing my education with two other resources: Code School and Codecademy.

    • Treehouse turned out to be great to have the big picture, and understand how all the parts were coming together.

    • Code School was very good to dive deep into each of the topics.

    • And in Codecademy they make you write down a lot, which was perfect to nail down concepts.

    This was basically my workflow. I started with the first courses of my track at Treehouse. When I finished with HTML & CSS, I was also checking the related resources in Code School and Codecademy. The same for JavaScript, Git and PHP in my case (Code School doesn’t count with PHP courses, but they do teach Ruby ☺).

    You can also check here a complete list of the courses I followed.

    5 Tips To Stay on Track

    During that time I discovered other things to be as important as following these courses.

    Find a partner

    The first one, I had a partner. I had someone to talk to, even if he was not an expert in that technology. Which was specially important in those days when my code was broken…

    Watch Tech Talks

    This is something that I discovered half of the way: watch Tech Talks. I used to watch one talk per day, most of the times during lunch. It helped me to keep the motivation up. Again, at Treehouse there are a lot of them. Totally recommended!

    Start a Pet Project

    This one was crucial. What you build is definitely not important. But once you have some knowledge, starting a pet project is the best way to keep learning. In my case I found a person online interested to build a web application. He was preparing for a big exam and the site would help him with that. He needed to introduce new topics, questions and their answers. I learned A LOT with this project.

    Breath In & Keep Coding

    This one took me a little bit more time to get. When something doesn’t make sense and you try and try and still nothing… leave it. Just keep going. If you hang in there for too long you might lose your motivation. And surprisingly one day, when you do not expect it, you will get it!

    Keep an Eye on Job Opportunities

    And the last one, keep an eye on job opportunities. I used to have dark moments every Sunday evening. I wondered whether I was learning something that people were asking for. And that’s when I was checking jobs descriptions.

    Life As A Web Developer

    Four months after I started this whole process, I saw a job offer for an internship. I had studied everything that they were asking for. So I applied for it and two weeks later I was already working there. After a month in the company, they promoted me to a junior developer.

    That’s the story about how I landed a job in tech.

    Recently I moved from Frankfurt to Amsterdam, having to leave my job there as a PHP Developer. During my first month in the city I was actively attending Meetups, where I met an experienced developer who convinced me to learn Ruby on Rails. My approach to learn it was quite similar and some weeks later I was having my first interview at Springest. I have been working with them for one month already and I am impressed about their way to encourage people to develop themselves both personal and professionally, not only through their site but also within the company.

    Starting to code was just the beginning of a long journey. As a developer you need to keep learning new things constantly. Online resources are still the best option for me, along with the awesome web community and people you work with.

    Read more
  • Support for SOI codes

    Today we took another step in making our data more complete by adding support for SOI (Standaard Onderwijsindeling) codes. The SOI standard has been developed by the CBS (Centraal Bureau voor de Statistiek, Statistics Netherlands in English). The goal of SOI is be a detailed coding standard by course level and subject. It is updated annually to reflect changes in the market.

    Read more

subscribe via RSS