More Lessons I Learned Working From Home

More Lessons I Learned Working From Home

In the previous article, we discussed the advantages and disadvantages to working from home. In a remote work setup, it is important to establish a fixed time and place for you to work. But there are more things that we need to take into account: communication and security. These are the additional lessons I learned while working remotely since 2012.

Communication is a high priority

My boss always emphasized that communication is the most important thing especially in the context of working remotely. If we are not able to communicate effectively, then the whole setup will fail. read more

Lessons I Learned Working From Home

Lessons I Learned Working From Home

We live in interesting times due to the COVID-19 pandemic. More and more companies are being forced to adopt a remote working setup (or working from home) for its employees. I have been working remotely full-time since 2012. This article discusses some of the lessons and tricks I learned throughout the years.

I understand that working from home does not apply to all industries. It is mostly applicable to jobs that involve working in front of a computer. My career is in software development which fits this set up comfortably. However it can also apply to other industries such as business process operations, accounting, and company administration. read more

Slightly off Rails

Slightly off Rails

I use Rails both professionally and personally for more than a decade now. Through the years, my usage of Rails also evolved together with new concepts and trends in web development. Here are some of the personal changes I am applying moving forwards on how I work with the framework.

Authentication using JWT

JWT.io
https://jwt.io/

JSON Web Tokens (JWT) provides a way to effectively secure API endpoints. As web applications move more to the front-end with the popularity of Javascript frameworks like React and Angular, JWT ensures that the connection between the front-end and the back-end remains secure.

However, I don’t believe that we should reinvent the wheel, especially when it comes to authentication. Thus I will still continue to use the devise gem. This library has been a staple in Rails applications for many years now and as a result has already gone through a lot of patching and bug fixes.

There’s also a gem called devise-jwt that makes it easy to integrate devise authentication using JWT, and I am using this library for present and future projects.

What this gem does is that after a user signs in, it automatically adds a JWT token to the Authorization header. This token can then be used by the front-end code to submit requests back to the server. The server checks the token and validates if the user has access to the endpoint or resource. Using the gem, this is being done automatically, and that user is available through the current_user variable.

You can still use the (default) session authentication as well, so you can have both a web application and a front-end client application (like a mobile app) using the same authentication mechanism.

dry-rb

Rails is an opinionated framework. This means it has its own way of doing things, and by following them it can make your work simpler and faster. These methods utilize the full features of the framework and lets the framework do the heavy lifting for you. Some people do not like this approach as it makes things less transparent and “magical”.

While Rails is opinionated, it is not restrictive. You can ignore built-in features or build your own without having the need to abandon the framework altogether.

https://dry-rb.org/

There are several libraries that enable you to work outside the Rails conventions. Some of the most popular ones are Trailblazer and dry-rb. Moving forward, I intend to use dry-rb more as I found that their modular approach to libraries is a great way to implement projects.

Here are some of the concepts that I found useful in dry-rb:

Transactions and Operations

Using the transaction concept allows us to think of a feature in terms of steps. This in turn enables us to break down a feature into smaller parts. It also allows for easier debugging and refactoring of code as we can create steps that essentially just perform one specific task of the whole.

As an example, let’s say we want to create an event and send an email to its participants. In a transaction, we can break this down into three steps: checking the event form parameters, creating the record, and then sending the emails.

require "dry/transaction"

class CreateEvent
include Dry::Transaction

step :validate_parameters
step :create_event
step :send_email, with: 'event.operations.send_email'

private

def validate_parameters(params)
# returns Success(valid_params) or Failure(errors)
end

def create_event(params)
# returns Success(event)
end
end

You can see that the validate_parameters and create_event methods are simply private methods of the transaction class. The send_email method however is not present in the class itself but is invoked as an external operation. For this example, we can have an operation class called Event::Operations::SendEmail.

Using operation classes allows us to create reusable functions. These operations can be called on any other transaction (or any other code really). In addition to being reusable and modular, it is also easy to test as each operation performs only one specific function.

Monads

Notice that the return values of the methods are Success() and Failure(). These are called monads and they help structure your responses so that methods communicate with each other more effectively. The value I get from this is it forces me to think of failure scenarios in the code. I can then handle success and failure conditions effectively without resorting to complex logic or nested if-else conditions.

Validations

dry-rb also has a library called dry-validation. Using this library you can define your own custom schema and validation rules. In Rails, the default schema and validation is usually tied to your database models. dry-validation provides the same feature that you can use on any code in your application.

It also enables you to define types in each of the fields in your schema. This can simplify your code as you are guaranteed that each field has the correct type. This also reduces potential bugs in your application.

Here is an example found in their official documentation. It describes how to use dry-validation in setting up the schema and the validation for a new User record:

class NewUserContract < Dry::Validation::Contract
params do
required(:email).filled(:string)
required(:age).value(:integer)
end

rule(:email) do
unless /\A[\w+-.][email protected][a-z\d-]+(.[a-z\d-]+)*.[a-z]+\z/i.match?(value)
key.failure('has invalid format')
end
end

rule(:age) do
key.failure('must be greater than 18') if value < 18
end
end read more

Rubyist’s intro to Python web development

I have been using Ruby professionally for more than a decade now. Until recently, I haven’t explored much outside of the Ruby and Rails community. That changed however after I completed a course in Foundations of Data Science. This made me curious about Python and how to build applications using it.

Python and Ruby have many similarities. Both are interpreted, high-level programming languages. Python also has support for Object-Oriented Programming and Functional Programming. In terms of syntax, they have a similar look and feel, aside from some fundamental differences such as Python being indent-driven.

You may find this article to be very similar to the Ruby on Rails guide I posted years ago. This is not accidental since my goal is to introduce Python web application development to someone who is already familiar in the Ruby space.

Installing Python

The very first step is to install Python itself in your computer. I recommend using pyenv to manage your Python versions. pyenv is a Python version manager, like rbenv. In fact, pyenv is a fork of rbenv and is re-purposed for Python. To install pyenv:

curl https://pyenv.run | bash

After installing, update your login shell configuration by adding the following, e.g. in ~/.zshrc

export PATH="/home/user/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"

Now we are ready to use pyenv to install a specific Python version. But first, we need to install some dependencies so we can compile Python from source:

sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl

Then, we can easily install a Python version, like 3.6.8 in this example:

pyenv install 3.6.8

If you are having trouble installing Python, it could be related to the OpenSSL version installed in your machine.

On Debian stretch (and Ubuntu bionic), libssl-dev is OpenSSL 1.1.x,
but support for that was only added in Python 2.7.13, 3.5.3 and 3.6.0.
To install earlier versions, you need to replace libssl-dev with
libssl1.0-dev. This is being tracked in
https://github.com/pyenv/pyenv/issues/945.

Once Python has been installed, you can opt to set the version (e.g 3.6.8) as your global version. This makes the Python executable available to all terminal sessions:

pyenv global 3.6.8

Package Management

pip is Python’s package manager, like rubygems or npm. If you installed Python, pip should also be available for you. If for some reason it is not installed, you can install it using the guide here.

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py $ python get-pip.py

Application-specific Packages

In Ruby/Rails we use the awesome library Bundler to handle application package management. We manage the packages using a Gemfile, and it gets converted into Gemfile.lock.

pipenv is similar to bundler, but its functionality extends beyond package management in the application. In this article we will use it similar to bundler so it will handle all the application package dependencies. To install pipenv, just use pip!

pip install pipenv

To specify the application packages, pipenv uses a Pipfile. An example is given below:

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
requests = "*"
flask = "*"
python-dotenv = "*"
flask-sqlalchemy = "*"
flask-migrate = "*"

[requires]
python_version = "3.6" read more