Mauro Morales

software developer

Tag: Ruby Gems

  • ActiveRecord Except

    August 19th was Whyday, and to commemorate it, I decided to write a gem called activerecord-except.

    WHAT IS IT?

    activerecord-except is a Ruby gem that extends the functionality of ActiveRecord, allowing you to select all the fields from a table, except the ones that you specify. For example, if you have a table users.

    development_db=# \d users
          Table "public.users"
                Column             | 
    -------------------------------+-
     id                            | 
     username                      | 
     password                      | 
     email                         | 
     first_name                    | 
     last_name                     | 
     phone                         | 
     ...
     created_at                    | 
     updated_at                    | 

    And you want to get all the fields except for the password, you’d have to pass each of them in your select clause like so

    User.all.select(:id,
                    :username,
                    :email,
                    :first_name,
                    :last_name,
                    :phone,
                    ...
                    :created_at,
                    :updated_at)

    Instead, using activerecord-except, can simplify your statement by saying only the field you don’t want, in this case, the password one

    User.all.except(:password)

    HOW DOES IT WORK?

    Under the hood, the except clause makes use of the traditional selectclause. So our previous example will produce the following query

    SELECT "users"."id",
           "users"."username",
           "users"."first_name",
           "users"."last_name",
           "users"."phone",
           "users"."created_at",
           ...
           "users"."updated_at"
      FROM "users"

    This is because the SQL language doesn’t provide such functionality out of the box.

    I don’t know what is the reason for this. I can only speculate that it’s to be more explicit and not be caught by surprise if a field in a table gets added/deleted/changed. However, * is also wildly used. In Rails for example, it is what you get, when you don’t specify a select clause in your query.

    The way I managed to make it work is by adding a method toActiveRecord::Relation which asks the model for all its attributes and rejecting those that match with the ones passed as arguments.

    klass._default_attributes
         .keys.map(&:to_sym)
         .reject { |attr| fields.include?(attr) }
    

    Note: As you can see, I’m using _default_attributes which starts with an underscore. This can mean that the method is not intended to be relied upon.

    Whether or not you might want to use in production, I leave up to you, where I really see the benefit of activerecord-except is for writing one-off scripts to extract data, because it makes them much easier to read.

    WANT TO GIVE IT A TRY?

    You can install it from rubygems or you can check the source code either on Sourcehut or GitHub.

  • Yes, Ship It!

    Last week I had the chance to participate in my first Hackweek. I never had such an experience in any other company I’ve ever worked for and between my colleagues’ reports about previous experiences and my own expectations I was very excited to see what was all the fuzz about.

    These type of events are not unique to SUSE, as a matter of fact Twitter and a bunch of other companies were also having their Hackweeks at the same time and I’m glad this is the case because after having the chance to participate in one I realize it’s a great way to promote creativity.

    A hackweek is basically a week were you get to work on anything you want to work on. You are not expected to deliver anything but instead encouraged to experiment and explore with anything you think is worth spending time on.

    In order to make the most out of Hackweek I decided to join a project and not start one of my own so I could do some pairing. This kind of interactions always make it a lot of fun for me plus I get to learn a ton. That’s how I joined Cornelius Schumacher to work on Yes Ship It! This is a project he had already started on his own so we were not doing everything from scratch.

    The approach of yes_ship_it is different from the typical release script. It doesn’t define a series of steps which are executed to make a release. It defines a sequence of assertions about the release, which then are checked and enforced.

    The first thing we decided to do together was a Rails App which allows you to track successful software releases. Since it was going to be 100% related to Yes Ship It! we decided to call it Yes It Shipped!. Let me show you how trivial it is to add it to a project like the formstack-api gem.

    1. Install the yes_ship_it gem
    $ gem install yes_ship_it
    
    1. Add a yes_ship_it.conf file
    $ yes_ship_it init
    
    1. Release!
    $ yes_ship_it
    

    By default yes_ship_it will check if:

    • you are in the right release branch (by default master) and the code was pushed.
    • the working directory is not missing to commit anything.
    • the version was update
    • the changelog was updated
    • a tag was added and published
    • a new version of the gem was built and published

    The aim is to make it as generic as possible so you can adapt it to anyproject you have. For starters you can remmove any check in the process and soon enough you will be able to add checks of your own.

    What I like the most about it is that I can run yes_ship_it at any time. I don’t need to remember or make sure what was the last step I did because that’s exactly what it will do for me.

    What do you think? Leave your comments below and remember to release early and release often!