Say hello to some of our women in engineering!

Posted by on June 25, 2021

We celebrated International Women in Engineering Day earlier this week with a video featuring some of our own. This inspired a few more of us to mark the occasion and say hello. What’s exciting is that there are many different routes to a career in engineering. Say hello to…

Katrina 👋


Who inspires you in the tech world?

I think I’ve been genuinely lucky to start out at FreeAgent. Over the years I’ve worked with some great developers and what’s been lovely is they’re quite a varied bunch in terms of their areas of interest, which I think helps make us a strong team. I was horrendously nervous when I started and was very conscious of the fact I was starting out late and without a traditional background in computer science. But from day one I felt welcomed. To name a specific person, I’d have to say Maria Gutierrez, who was previously with FreeAgent and is now at Twitter. She was the person who first suggested I could have the skills for a move to tech and without her support and encouragement I would not have made the move – I’d still be in my other life feeling like a square peg in a round hole. And she’s still always there now if I want some advice or guidance.

What’s your favourite programming language or technology?

Ruby was the first language I learned and it’s one I use a lot at FreeAgent so I think I’d have to say Ruby.

Can you tell us how you started your career journey in engineering?

When I was on maternity leave with my second child, around six years ago, I was reassessing my career and realised I really wanted a change. A friend had suggested programming to me and I’d tried out a lot of online courses and tutorials and found I really enjoyed it. It was just around that time that CodeClan launched in Edinburgh so I went along to an info session, had an interview and signed up. I loved the course and afterwards joined FreeAgent, where I’ve been for 4 1/2 years now, moving from junior engineer to mid-level. Making the career change was the best decision ever and I have never regretted it.

What is your superpower? ✨

I think I’m adaptable. Things are always changing and it helps to be able to go with the flow and be open to new things.

Anda 👋


Who inspires you in the tech world?

Laura Kalbag for her excellent work on accessibility, social justice and privacy.

What’s your favourite programming language or technology?

I have a love/hate relationship with Javascript, sometimes I really enjoy it and sometimes I question why it exists. I also think Ruby is great!

Can you tell us how you started your career journey in engineering?

I studied Computer Science way back in high school. I’ve always enjoyed computers and technology ever since I was little so it made sense to stay in the field. I studied Computer Science & Software Engineering in Uni. Although I do have a degree, I don’t think it should be a requirement for a career in engineering. Everyone’s path is different and we should learn from people with different backgrounds and points of view.

What is your superpower? ✨

Communication! I love transparent communication, keeping people in the loop and making sure we’re all on the same page. I also love learning which is an asset in any career!

Sheila 👋


Who inspires you in the tech world?

The first person to really inspire me within the tech world on a personal level was Ann Budge. Ann set up Newell & Budge with business partner Allison Newell in 1985. The company specialised in producing bespoke software and IT systems, serving clients including government and some of Edinburgh’s leading banks and insurance companies. I was employed by Newell & Budge in Edinburgh as a graduate software engineer. I discovered that I really enjoyed working with clients to understand their requirements and deliver software solutions to enable them to run their businesses more effectively. I was impressed how Ann had built the business so successfully and later it inspired me to take a risk and set up my own.

What’s your favourite programming language or technology?

I have enjoyed working with many programming languages in my career but I do have a soft spot for C#.

Can you tell us how you started your career journey in engineering?

Engineering found me I think. I wasn’t sure what I wanted to do when I applied to university. I was offered a place at Trinity College in Dublin to study Mathematics and Computing and turned it down as I decided I didn’t want to take computing! Instead, I chose to study Accountancy and Finance at Heriot Watt as that seemed like a sensible career choice. While I very much enjoyed aspects of the course – Finance, Tax, Business Organisation – I wasn’t convinced Accountancy was the job for me. I wanted to do something more creative. I applied for a postgraduate course in Information Systems which was geared up for graduates with Social Science degrees to learn computing. I discovered I really enjoyed programming, especially gathering user requirements and delivering solutions to meet their needs. I was fortunate to be offered a graduate software engineering role at Newell & Budge and so my career journey began!

What is your superpower? ✨

Resilience. I like to prove the naysayers wrong. I set up a Website Monitoring company just as the dot com bubble burst and persevered to build a successful business.

Lorna 👋


Who inspires you in the tech world?

Cat Swetel | Sal Freudenberg | Kim Crayton

What’s your favourite programming language or technology?

Anything that allows screensharing for collaborative coding, plus git for the same reason. I am at my best when I’m working as part of a group, which surprises a lot of people when they learn that I’m autistic and an engineer. 

Can you tell us how you started your career journey in engineering?

My then-employer decided to close their entire Edinburgh operation, which gave me the chance to really think about what I wanted to do. I went along to codebar Edinburgh for several months, and was fortunate to have some really good coaches who helped me explore not just the technicalities of coding but also the thought process behind this kind of problem solving.  Once I was certain that this was the right direction for me, I did the 16 week course at CodeClan.

What is your superpower? ✨

I’m a tractor: I’m not fast, but there’s very little that will actually stop me.

Claire 👋


Who inspires you in the tech world?

Managers or team leaders who are genuinely interested in widening the recruitment net to include people from all walks of life, not just those with specific qualifications or history, and who truly value the diversity and fresh perspectives resulting from this. Valerie Dryden is an Edinburgh-based leader in tech and was also my first tutor at CodeClan – she was only there for a few weeks of my course but made a huge impression on our class, and she’s out there pushing for change in recruiting and building genuinely diverse teams.

What’s your favourite programming language or technology?

Whichever one I am using the most at the time, so right now, Ruby! But it has previously been C# and Typescript, so I’m sure it’ll change again…

Can you tell us how you started your career journey in engineering?

I went to CodeClan, Scotland’s training program for people seeking a new career in software engineering. Previously I had worked in the events and festivals industry for many years, so it was quite a shift. I took the plunge after realising how much I enjoyed logic and creative problem-solving, and because I wanted to move into an industry that was growing fast and had more opportunities.

What is your superpower? ✨

Details: it was a superpower in the events industry and perhaps even more so now. Being able to see the intricacies of a problem or a project and find ways to address them. I also try to always ensure every voice in a team is being heard, since that’s the only way we will get the best result.

Titlecase, underscore and laser guns

Posted by on June 10, 2021

Not so long ago, I had an opportunity to peek under the hood of titlecase and underscore methods, the tiny cogs of the “Rails magic” machine. The latter turned out to be a very interesting function—a lot of hard-to-follow transformations, secret injections and the like. All of these bits significantly contributed to an odd-looking bug I’ve been working on. 

Today, we’ll unravel the implementation of both methods and look in the eye of regular expressions. But first of all, let’s see what this bug was about.

Note: This post describes the function behaviour present in Rails 6.1.3 and may change in the future.

The Bug

The FreeAgent sign-up process can take a while when you have to fill in all business details by hand. Thankfully, we have an option of automating this process by using the “Find company details” feature. The search is simple—just provide the company name and all relevant fields will be filled in with data retrieved from the Companies House API.

Sometimes, the search results didn’t look as expected:

A screenshot of a dropdown menu that shows a list of company names with extra spaces

Hmm, “RTI”? In our domain it’s a pretty special acronym but it’s not something that our user expects to see in the name of their company. It made me wonder how it is possible that RTI is found and formatted this way here. It doesn’t seem to be on our side. We just call this one method:


So, we take a string and make a pretty title out of it, right? Well, it’s a bit more complicated. Rails’s String::titlecase internally calls an identically named method defined in ActiveSupport::Inflector module, a part of the machine I mentioned before. ActiveSupport::Inflector operations allow transformation of strings such as pluralisation, converting namespaces to paths and many more. As a bonus, it has the power of recognising acronyms in strings including these defined by a user. RTI happened to be defined in our config/inflections.yml file. Let’s take a look:

# good
"partition arts".titlecase => "Partition Arts" 

# whoops  
"PARTITION ARTS".titlecase => "Pa RTI Tion Arts" 

As you can see, there’s a link between uppercase characters and finding acronyms. We deal with company names so we don’t want to infer any acronyms from their names. It suffices to add downcase to fix the bug:


But why is that? Where precisely do we find RTI in a string? Let’s find out.

The Big Picture

titleize, the true form of titlecase, is powered by a composition of two methods: humanize and underscore:

humanize(underscore(word), keep_id_suffix: ...)
.gsub(...) do |match|

The underscore method does the heavy lifting of inferring potential words and acronyms from CamelCase and hyphenated strings. The humanize method, on the other hand, applies a couple of rules to transform a string so it looks acceptable to the end user. This includes replacing underscores with spaces, capitalising the first letter of the string, converting all letters but acronyms to lowercase and the like. For now, we’ll ignore the gsub definition to keep things simple. The general flow of this function is:

  1. Get an underscored version of word
  2. Feed it to the humanize method
  3. Apply regex defined in gsub to word
  4. Iterate over each of them and convert to uppercase

underscore Deep Dive

You might’ve been thinking, “It’s not a big deal! underscore just places underscores between words!”. Well, sort of. At its core, underscore is intended to transform CamelCase, namespaced and hyphenated words into underscore separated strings:

"testingUnderscore".underscore  => "testing_underscore"

# Oh!
"testing underscore".underscore => "testing underscore" 

Now, let’s take a deep breath and look at the definition:

def underscore(camel_cased_word)
 return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)  
 word = camel_cased_word.to_s.gsub("::", "/")  
 word.gsub!(inflections.acronyms_underscore_regex){"#{$1 && '_' }#{$2.downcase}"}    
 word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2' ) 
 word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')!("-", "_")

There’s a lot to unpack. For simplicity, I numbered some of the regular expressions so you can go back and see the actual code when I explain them later on. In our “debugging session”, we’ll pass the “PARTITION ARTS” string in, so we can see each transformation that contributed to our bug.

The function flow

1. Do an early check if matches the parameter. If this is not the case, return the word with no substitutions. This is a pretty simple regular expression—it’ll match only if there’s at least one uppercase letter, hyphen or a namespace separator:

There’s a match for our argument so we continue our journey.

2.  If finds a namespace separator, it is replaced with a slash. This line helps with inferring paths from namespaced modules/classes strings. As we don’t have such characters in our string, word is equal to the parameter.

3. Try to match the string against inflections.acronyms_underscore_regex. It’s a regular expression to test if any user-defined acronyms “hidden” in the string[1]. If this is the case, we catch the acronym and letter that precedes it. We have a match on our string:

The gsub that uses this acronyms regex defines the substitution as follows:

A diagram showing a string interpolation between two groups of regex matches

appends an underscore to the first group (“A”) and concatenates it with the lowercase version of the acronym. Now, word is equal to “PA_rtiTION ARTS”

4. Match uppercase letters/digits in one group and two letters in another, a pair of uppercase-lowercase letters:

For example, a match on the “CamLLcase” string would be split into two groups: 
Group 1: “L”
Group 2: “Lc”

Later on, gsub would transform the string and place an underscore between these groups. So, “CamLLcase” → “CamL_Lcase”. As we have no match to this regular expression, this transformation doesn’t apply here—there’s no change to our word.

5. Match all occurrences of lowercase/digit-uppercase letter pairs and insert “_” between them:

This is the last step of extracting the earlier identified acronym. In our case it’s just one pair:

So ④ will transform word to “PA_rti_TION ARTS”.

6. Replace all `-` for `_` to finalise the underscore substitution

7. Return a lowercase version of the processed string

The final form of word is “pa_rti_tion arts”.

Going back to titleize

After the underscore method returned a transformed string, it’s passed to humanize:

                             # default value ↴
humanize(“pa_rti_tion arts”, keep_id_suffix: false)

This method replaces all underscores with spaces and capitalises the first letter of the string and all acronyms. Here, this changes our string to “Pa RTI tion arts”, which is pretty close to what was rendered in the autocomplete list.

But wait, we still have a long-forgotten gsub to analyse:


Before we start panicking, we’ll break it down into more digestible chunks:

A diagram explaining regular expression introduced in the mentioned gsub

Word boundary is a matcher that “moves” the regular expression so it can be applied from the beginning or end of a word (e.g. after or before a space character). Once we’re set in the right position, we do a negative lookbehind match (indicated by ?<!). This is a check that ensures that the regex it describes does not match the string. If the negative lookbehind is happy with what it got, the expression matches the next lowercase letter and captures it. In our case that would be:

So, as a result, we get a list of lowercase first letters in the string. Each of them is passed to this block and capitalised:

humanize(...).gsub(...) do |match|

We are finally done with the transformations. We end up with “Pa RTI Tion Arts”.


A fix of calling downcase in result["title"].downcase.titlecase was a result of trial and error. Now we know why it works. The underscore method is very eager to find acronyms but only if it finds any uppercase letters first.

It makes sense given how we define acronyms but it has unintended consequences like finding acronyms in all-capitalised strings. Unfortunately, this is not obvious without understanding the inner workings of the titlecase/underscore method.

Also, it looks like titlecase was innocent all the way. I’m sorry, buddy.

[1] – To be more specific, it checks if an acronym is preceded only by letters and digits and followed by non-lowercase characters. Full definition.