New Site, New Job

Jun 03 2024 4 minute read

My adventures at StreetEasy came to a close on March 12 of this year. During my tenure as a Senior Software Development Engineer at Zillow Group, I played a key role in migrating StreetEasy to a Commands and Queries pattern within the Rails monolith, extracting tightly coupled controller logic into reusable service objects. In addition I participated in the consolidation of NakedApartments into StreetEasy, ensuring a smooth transition and alignment of branding strategies.

While leading two pods as a Technical Lead, I was instrumental in migrating StreetEasy from a Rails monolith to Java Micronaut services. Additionally, I contributed to the creation of a subscription-based system called the Industry Experts Program for agents interested in listing on StreetEasy.

Working at StreetEasy provided me with the opportunity to hone my skills in various technologies and frameworks. I was able to leverage my expertise in Ruby, JavaScript, and Java to drive the faster delivery of high-quality technology solutions and improved user experiences. My experience in full-stack development, coupled with my passion for harnessing machine learning technologies, allowed me to make substantial contributions to the team.

Leaving StreetEasy was a bittersweet moment for me. While I was sad to say goodbye to my colleagues and the projects I was passionate about, I am excited about the new opportunities that lie ahead. I look forward to applying the skills and knowledge I’ve gained at StreetEasy to new challenges and continuing to grow both personally and professionally.

With that being said, I’ve accepted a new role as a Senior Software Engineer at Root Insurance! I am thrilled to join an innovative company that is redefining the insurance industry with technology and data-driven insights.

At Root Insurance, I will be working remotely from Ohio, contributing to the development of cutting-edge solutions that leverage telematics and machine learning to offer personalized and fair insurance rates. This role provides an exciting opportunity to apply my extensive experience in software engineering, particularly in areas such as system architecture, and full-stack development.

I am particularly excited about the chance to work on scalable systems and to be part of a team that is committed to pushing the boundaries of what technology can achieve in the insurance sector. Joining Root Insurance allows me to bring my skills in Ruby and JavaScript to a new and challenging environment, where I can continue to grow and make meaningful contributions.

I look forward to collaborating with my new colleagues at Root Insurance and being part of a mission-driven company that is making a tangible difference in people’s lives by simplifying the insurance process and providing more equitable solutions. This new chapter in my career promises to be both challenging and rewarding, and I am eager to get started.

Additionally, as part of the job hunting process, I decided to redesign my personal site. The new site, built with Jekyll and Tailwind CSS, showcases my portfolio, highlights my professional journey, and serves as a platform to share my thoughts on software development and technology.

Using Jekyll allowed me to create a static site that is fast, secure, and easy to maintain. I took advantage of Tailwind CSS to design a clean and responsive user interface, ensuring that the site looks great on any device. The combination of these technologies enabled me to focus on content creation while providing a modern and visually appealing experience for visitors.

The redesign process was a valuable opportunity to apply my front-end development skills and to experiment with new design patterns. It also allowed me to reflect on my career achievements and present them in a cohesive and engaging manner. You can check out the new site at aaronmallen.me to see my latest projects, read my blog posts, and learn more about my professional background.

I plan to write a detailed guide soon, outlining the step-by-step process of the redesign to share knowledge on using Jekyll with Tailwind CSS for personal site development. In the meantime, you can check out the source code for my personal site on GitHub.

ActiveInteractor

Jan 26 2019 6 minute read

This weekend I released v1.0.0 of ActiveInteractor, an implementation of the command pattern for Ruby with ActiveModel::Validations based on the interactor gem with rich support for attributes, callbacks, and validations, and thread safe performance methods.

I wanted to go over some of the basic usage of the gem. An interactor is a simple, single-purpose service object. Interactors can be used to reduce the responsibility of your controllers, workers, and models and encapsulate your application’s business logic. Each interactor represents one thing that your application does.

ActiveInteractor’s main component is called an interactor, each interactor has it’s own immutable context which contains everything the interactor needs to do its work. When an interactor does its single purpose, it affects its given context. There are two kinds of interactors built into ActiveInteractor: basic interactors and organizers. A basic interactor is a class that inherits from ActiveInteractor::Base and defines a #perform method.

Basic Usage

Most of the time, your application will use its interactors from its controllers. The following controller:

class SessionsController < ApplicationController
  def create
    if user = User.authenticate(session_params[:email], session_params[:password])
      session[:user_token] = user.secret_token
      redirect_to user
    else
      flash.now[:message] = "Please try again."
      render :new
    end
  end

  private

  def session_params
    params.require(:session).permit(:email, :password)
  end
end

can be refactored to:

# app/interactors/authenticate_user_context.rb
class AuthenticateUserContext < ActiveInteractor::Context::Base
  attributes :email, :password, :user, :token
  validates :email, presence: true,
                    format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :password, presence: true
  validates :user, presence: true, on: :called
end

# app/interactors/authenticate_user.rb
class AuthenticateUser < ActiveInteractor::Base
  def perform
    context.user = User.authenticate(
      context.email,
      context.password
    )
    context.token = context.user.secret_token
  end
end

# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def create
    result = AuthenticateUser.perform(session_params)

    if result.success?
      session[:user_token] = result.token
      redirect_to result.user
    else
      flash.now[:message] = t(result.errors.full_messages)
      render :new
    end
  end

  private

  def session_params
    params.require(:session).permit(:email, :password)
  end
end

Organizers

An organizer is an important variation on the basic interactor. Its single purpose is to run other interactors.

class CreateOrder < ActiveInteractor::Base
  def perform
    ...
  end
end

class ChargeCard < ActiveInteractor::Base
  def perform
    ...
  end
end

class SendThankYou < ActiveInteractor::Base
  def perform
    ...
  end
end

class PlaceOrder < ActiveInteractor::Organizer::Base

  organize :create_order, :charge_card, :send_thank_you
end

In a controller, you can run the PlaceOrder organizer just like you would any other interactor:

class OrdersController < ApplicationController
  def create
    result = PlaceOrder.perform(order_params: order_params)

    if result.success?
      redirect_to result.order
    else
      @order = result.order
      render :new
    end
  end

  private

  def order_params
    params.require(:order).permit!
  end
end

The organizer passes its context to the interactors that it organizes, one at a time and in order. Each interactor may change that context before it’s passed along to the next interactor.

Organizing Interactors Conditionally

We can also add conditional statements to our organizer by passing a block to the .organize method:

class PlaceOrder < ActiveInteractor::Organizer::Base
  organize do
    add :create_order, if :user_registered?
    add :charge_card, if: -> { context.order }
    add :send_thank_you, if: -> { context.order }
  end

  private

  def user_registered?
    context.user&.registered?
  end
end

Working With Rails

If you’re working with a rails project ActiveInteractor comes bundled with some useful generators to help speed up development. You should first run the install generator with:

rails generate active_interactor:install

In some instances you may want to use an ActiveRecord model as a context for an interactor. You can do this by calling the .acts_as_context method on any ActiveRecord model, and then simply call the .contextualize_with method on your interactor or organizer to point it to the appropriate class.

# app/models/user.rb
class User < ApplicationRecord
  acts_as_context
end

# app/interactors/create_user.rb
class CreateUser < ApplicationInteractor
  contextualize_with :user

  def perform
    context.email&.downcase!
    context.save
  end
end

CreateUser.perform(email: 'HELLO@AARONMALLEN.ME')
#=> <#User id=1 email='hello@aaronmallen.me'>

I hope the ruby community finds this gem usefull and I’d love any feed back, issues, or stars on the repository that you’re willing to give. Detailed usage for the gem can be found on the wiki. Technical documentation for the gem can be found on rubydoc.

Your Framework is Dead; Long Live Your Framework

Jan 14 2018 4 minute read

Let me preface this with the fact that I am primarily a Rails Developer. Inherently this typically means I have a lot of respect for David Heinemeier Hansson (DHH) both as an engineer and as a person. That being said, a few months ago I saw him perpetuate an ongoing issue in the developer community and it made my heart sink a little bit.

To understand this tweet you have to understand the climate of the Rails community at the time, and really, currently still. Many have claimed that both Ruby and Ruby On Rails have been on a downward spiral towards obsolescence largely because of a lot of the “new hotness” coming out in the javascript world and partly because of ruby’s supposed performance issues. Shortly before this tweet a major code camp dropped rails from its curriculum, and there have been a few other snags for the ruby community as well. So ruby developers found themselves in a very similar position PHP developers have been in for the last 5 to 10 years.

I contend that DHH, although I feel he probably should have thought a bit before pressing that tweet button here, isn’t the problem. Hell, Joe McCann isn’t the problem here either. I honestly think the guy just chose a poor time to make a tone-deaf joke without really understanding how sensitive the RoR community was at the time. The problem is software developers generally seem to adopt some form of superiority complex in reference to their language or tools of choice. This is not a new thing. Think back to the days of Emacs vs VIM, or even further back to the days when you were judged based on the Linux distribution you chose. We devs have always been fanatical about the tools we choose to do our jobs.

I think its important for us as developers to form opinions about frameworks, languages, and tools. There is nothing wrong with enjoying what you do. However, I think it is equally important to remember that others may have different opinions than you do and, contrary to what you may believe, that does not make them wrong.

When beginning a project the most important thing to consider when choosing a tech stack is what is the right tool for the job. Now, there are a lot of implications there. You have to consider if a particular framework is appropriate. You wouldn’t use Vue to build out a REST API for instance. Are you going to be hiring a team to help with the project? Then you have to consider the availability of developers familiar with the framework you’re using. Are you on a tight schedule? Then you need to consider which framework will be the quickest to implement and iterate through. There are a lot of factors and each project is different. At the end of the day, you have to pick the right tool for the job… period. That may mean you find yourself leaning more towards a framework you’re not overly familiar with or more towards a framework that is “dead”.

The polarity and rejection of those that have different approaches to a particular problem get us nowhere as a community. I would argue that what it does is prevents a die-hard fan of a particular framework from ever wishing to experience anything outside of their chosen fandom. We need to spend less time worrying about the popularity toolsets that we use and more time concentrating on building the internet and making it bad ass.

So, to summarize, whether you’re a PHP developer, a Ruby developer, a Java developer, or a Node developer, we can all agree on one thing; we love what we do. We are living in an unprecedented time where deploying a website is one CLI command away, and there is always something new to learn or some amazing problem to solve.