Lessons from attending my first Women-in-Tech Event

How I went from being a skeptic to ardent supporter of the cause

Skepticism about WiT events

During the four years that I have worked in the tech industry, I have always been a little skeptical of women-in-tech events. I found women-only events a bit uneasy — if skewed gender ratio was an issue, why are we perpetuating it with our events? But the past few months changed my mind. I realize that I was actively contributing to the landscape of the technical workforce whether I thought the issue was relevant to me or not.

How I became a woman in tech

I came to software engineering through a slightly unconventional education path — by attending General Assembly Web Development Immersive program. I did very well in the course and didn’t feel like I was less capable than other male students.

Compared to my previous career in fashion and digital marketing, the tech industry was a great improvement in terms of pay and working conditions.

At my second software job, I had a smart, capable female mentor who was a great leader. She gave me the impression that it was completely normal for women to be technically excellent and hold a leadership position in tech.

And I know that I am not the only woman in tech who does not think gender discrimination was a problem. One of our junior engineers shares some of the same concerns as I do. Having earned a Computer Science degree at Hunter College, she had attended many WiT events and felt like they might be counterproductive:

“We hear all these negative stories about women in tech. The fact that there are fewer females in the workplace makes them think men must have done something to cause it,” she said.

What changed my mind

What got me really thinking about WiT was being promoted to Engineering Manager for Narrativ frontend development team in April (a team lead position with people management responsibilities). I took over the hiring process for my team and was astonished by the numbers!

Only 15% (9 out of 59) of the resumes I read belonged to a female candidate.

This number would probably be even lower if I account for the backend roles for which we are hiring. It made it extremely difficult to hire a qualified woman from all the candidates who go through our process. As of July 2018, our engineers consisted of 37% women. But as the team grows rapidly, by October, this number would be reduced to 30% if we followed general headcount trends in technology. This is when I realized I needed to take some serious action if I wanted to maintain a diverse, gender-balanced team.

I may be luckier than I thought, having had a great female mentor early in my career. I realize that, in my current position, I could really create an impact for other female engineers. I started looking into my professional network on LinkedIn to find ways to be more involved. Very timely, I came across Zocdoc WiT event, which boasts an impressive panel of women in technical leadership (password: WomenInTech).

Takeaways from Zocdoc Women in Tech panel

What I liked about the Zocdoc panel was that it wasn’t just focused on hiring more women into technical roles. The goal was to increase diversity and inclusivity in companies’ cultures. Hosted by Ruxandra Levy, Director Engineering at Zocdoc, the panelists featured some amazing female directors of engineering, including Swati Vauthrin (Buzzfeed), Ashley Miller(Datadog), Stacey Gorelik (Flatiron Health) and Farzana Nasser, President of mBolden.

After hearing stories and advice from the panelists and audience members, I began auditing Narrativ on some of the points that resonate most with me:

  • Do our job descriptions highlight the fact that the company values diversity and inclusiveness? (And I’m not talking about the Equal Employment Opportunity disclaimer.)

Our job description does little to reflect this philosophy even though this is something the CEO is passionate about.

  • Are women and people of color represented on the company’s About Us page? Blog? Do candidates see or meet with people who look like them during the interview process?

Our About Us page is OK but women are underrepresented on the blog. This is why I told myself I really needed to write this post.

  • Are we clearly communicating the vitality of hiring diverse candidates to recruiters? Are we utilizing employee referral as a way to attract and vet diverse candidates?

Narrativ recently announced an official employee referral program, so hopefully we’ll be getting some good candidates through this channel. I also communicated this to an external recruiter I’m working with. It seems like I’m getting more female candidates from him since he knows I respond well to them.

  • Do we have women in leadership positions? Candidates like to know that they can receive mentorship and be advocated for promotion and raises.

This is one of the areas where Narrativ is doing well. A lot of female candidates I speak to, especially at the junior level, highlight mentorship as one of the main things they look for in their next role.

  • Are we supporting tech programs with good gender ratio?

This seems like a no brainer — support educational programs that funnel your hiring pipeline. Narrativ has been involved with CodeNow and Code to Work, both of which boast a 50–50 gender ratio, and we hope to do much more in the future.

Final thought

Sitting at the room full of female engineers at Zocdoc panel, I wondered how many of them used to think WiT issues didn’t apply to them, and what the turning point was for each of them. The biggest realization for me was that, if you are not actively working to promote diversity in your workplace, you are hindering its progress. It is no longer enough to show up and do your job. Men and women, straight and gay people, white people and people of color all play their role in shaping the face and future of the tech industry.

I have always been a firm believer that we need more women in leadership positions, whether it be in politics, the C-suite or engineering teams. Recently, I made a commitment to educating my colleagues about what they could do to help support diversity initiatives (e.g. introducing iMentor — a mentorship program for first-generation college students). As I am writing this blog post, I’m brainstorming a ton of ideas for improving the hiring pipeline, team building and cultural sensitivity training. I want to get others on board in this journey with me, one at a time, and hope to record my progress on this blog.

ActiveRecord: Change foreign key to a field other than the join table’s id

A good example for this implementation is when you have a table of retail stores that references a table containing US states. By convention, when adding a state reference to the stores table, a state_id column is created:

class AddStateToStores < ActiveRecord::Migration
  def change
    add_reference :states, :store, index: true, foreign_key: true

But say you want to see the human readable state code rather than its id when querying stores because joining two tables every time is too much work. You may want to change the foreign key from state_id to state_code.

Here is how it’s done step by step (referencing this SO answer):

– Add a state_code column to stores table and update the new state_code column during migration using a join statement:

class AddStateCodeToStores < ActiveRecord::Migration
  def up
    add_column   :stores, :state_code, :string
    query = "UPDATE stores AS A SET state_code = B.code FROM states AS B" +
            "WHERE A.state_id = B.id"

  def down
    remove_column :stores, :state_code, :string

– Specify a different foreign key for states:

class Store << ActiveRecord::Base
  belongs_to     :state, foreign_key: 'state_code',
                         primary_key: 'state_code'

– Now you can safely drop the state_id column from the stores table.

Testing: Set up shoulda matchers + VCR cassettes

The more I progress into my career as a software engineer, the more I realize the importance of test coverage. I don’t do TDD but find a lot of value to a decent test coverage. When you push a feature branch to Github and your continuous integration tool (in my current case Semaphore) tells you that tests fail, it is much faster and reliable to fix your logic or your test right away, rather than encountering a bug later on.

I plan to do some posts on testing, beginning with how to set up shoulda matchers and VCR cassettes (with Rails and RSpec).

Shoulda matchers

Shoulda matchers is a gem by Thoughtbot that provides quick helper phrases to test common functionality of Rails. In the Bedrocket API, we use shoulda matchers mostly to to test model validations and associations, but the library also has some Action Controller matchers.

– Example:

# item.rb
class Item
  validates       :name, presence: true
  belongs_to   :category

# item_spec.rb
describe Item do
  it { should validate_presence_of(:name) }
  it { should belong_to(:category) }

Installing shoulda-matchers

Personally I’ve ran into an error while installing gem shoulda-matchers:

Failure/Error: it { should validate_presence_of(:email) }
undefined method `validate_presence_of' for #RSpec::Core::ExampleGroup::Nested_1:0x105aa4938
# ./spec/models/user_spec.rb:4

I’ve searched and found out a way to avoid this error:
– Gemfile: Put shoulda matchers only in group test, with require: false param.

group :test do
  gem 'shoulda-matchers', '~> 2.8.0', :require => false
  gem 'fabrication'

– spec_helper: Require shoulda matchers

require 'rspec/rails'
require 'shoulda-matchers'


VCR Cassettes

VCR Cassettes records HTTP responses in yml files and “replay” them later for faster testing. It needs to be used with a HTTP stubbing tool, in this case webmock.

– Setting up:
+ Require the gems in group test:

group :test do
  gem 'webmock'
  gem 'vcr'

+ Configure VCR in spec/spec_helper.rb:

VCR.configure do |c|
  c.cassette_library_dir = 'spec/vcr'
  c.hook_into :webmock

cassette_library_dir is the folder where the responses are saved.

+ The controller spec is like so:

describe 'AnalyticsController', vcr: { match_requests_on: [ :host ] } do
  describe 'write analytics' do
    # contexts and expectations

– How it works:
+ match_requests_on parameter tells your spec when to use VCR pre-recorded responses for the result of the test. In this case, I simply want to match all requests of a certain host. But VCR also allow you to match requests by HTTP method, specific URI, URI path, URI query string, request body and headers (request matching doc).

+ Record mode: The default mode is record: once. This means VCR records the HTTP response when there are no yml files present for that request. When the spec is run subsequently, VCR will use the recorded response instead of making the request again.

+ See all record modes. To change record mode, simply add it as an argument:

describe 'AnalyticsController', vcr: { match_requests_on: [ :host ], record: new_episodes } do

+ When using the record once mode, simply delete the yml files to re-record responses. You should remember to re-record when code is changed to make sure that the spec still works correctly.

Safely plug a Rails app into an existing database

rails deploymentTraditionally there’re a few ways to set up your Rails database using rake tasks:
rake db:create db:migrate
Create a new database and run migrations
rake db:schema:load
Drop database if it exists and create tables according to your schema.
rake db:setup
Will run both rake db:schema:load and rake db:seed

db:schema:load is problematic. It is suggested in Rails schema.rb file that this is an efficient way (compared to db:migrate) to set up your database. However, it assumes that a) you have a database dedicated to the Rails app, b) have no existing data. But what if you want to create tables for your Rails app in an existing database with other important data?

Here’s a guide I’ve come up with on how to forgo migrations and integrate your Rails app into an existing database:

 1. Create tables in your production database
Feel free to namespace them like this: myproject_users instead of just users.

2. Edit database.yml
Specify the name of your database and the user/password that has access to it under the corresponding environment setting (development or production).

3. Void migration files
Under db/migrate, either comment out the files’ content or change their extension to .txt.

4. Schema dump
db/schema.rb is auto generated by running migrations. Since you don’t plan to run them, rake db:schema:dump will update schema.rb and allow it to be used with ActiveRecord.

5. Set custom table names for models
If the name of the tables are different from ActiveRecord convention (e.g.: you namespace the tables), add this to the model self.table_name = "[custom table name]". This will help Rails find the tables and avoid error.

Hope that was somewhat helpful. I’m also looking into deploying with Capistrano and submitting a pull request that would give a warning when you try to run rake db:schema:load.

The Absolute Beginner’s Guide to Capybara/RSpec

Sometimes the biggest challenge of using a new tool is not the syntax (there are always many examples for that) but getting set up. This is especially true and sometimes challenging for Rails, which is a convention-over-configuration kind of framework.

The situation

I need to write functional (aka integration or end-to-end) tests for a one-page app that relies entirely on AJAX to interact with a REST API.

Picking the tool

At the beginning I considered Cucumber. But I started seeing a lot of documentation for using Capybara in conjunction with RSpec, which I’m somewhat familiar with. It’s said to have an [intuitive API](http://rubydoc.info/github/jnicklas/capybara) and uses an easy to understand DSL (domain-specific language). So I decided on using Capybara/RSpec.

Running into problems

It was rather challenging to figure out how to configure the two gems and where to put the tests inside the ‘/spec’ folder. After about 2 hours and running ‘rspec’ unsuccessfully 30 times, I narrowed down the *key* steps in setting up Capybara test framework in a Rails app:

1. Gemfile

group :development, :test do
  gem 'rspec-rails'
  gem 'capybara'

2. spec/spec_helper.rb

require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/dsl'

The first two lines are automatically generated when you do ‘rails g rspec:install’. However, you need to require the capybara pieces manually.

3. Config the gems in spec/spec_helper.rb

Apparently selenium is the default driver for Capybara but I set it explicitly to be safe (actually I was trying everything I could get my hands on).
Capybara.default_driver = :selenium

You also need to include Capybara::DSL module so you can use phrases like ‘visit ‘/’ ‘, ‘fill_in’, ‘click_button’ in the tests.
RSpec.configure do |config|
  config.include Capybara::DSL

4. Where to put spec files

For RSpec, tests go under ‘spec/lib’. However, with Capybara, I have seen tests being put both under ‘spec/features’ and ‘spec/integration’. I went with the latter: ‘spec/integration/name_spec.rb’

5. Require spec_helper

At the top of each of your test file, put ‘require ‘spec_helper’ ‘

6. Test syntax

According to documentation I have come across, you can write tests either with RSpec or Capybara conventions:

describe 'log in process' do
  it 'lets user log in' do
   # Test goes in here

I went with the Capybara way:
feature 'log in process', :js => true do
  scenario 'lets user log in' do
    # Test goes in here

`:js => true` is supposed to help you switch to the Capybara.javascript_driver (instead of the selenium default). However, my app ended needing to use selenium web driver.

7. Capybara DSL syntax

feature 'log in process', :js => true do
  scenario 'lets user log in' do
    visit '/sessions/new'
    fill_in 'Email', :with => 'user@example.com'
    fill_in 'Password', :with => 'password'
    click_button 'Sign in'
    expect(page).to have_content 'Success'

8. Capybara selectors

For ‘click_link’ you can select the element by id or text. But for ‘click_button’ or ‘fill_in’, you have to select by the button value or input placeholder value.
click_link('Link Text')
click_on('Link Text') # clicks on either links or buttons
click_on('Button Value')

You can also find element by its id or html tag:
find_field('First Name').value

9. Web driver!

Last but not least, after I set up everything else correctly and was able to run rspec without getting `undefined method` error for Capybara, my terminal told me I was missing this gem:
gem 'selenium-webdriver'


As promised, when you successfully execute Capybara, the test will open up a browser and fill out username and password in the field you told it to and decide whether it fails or succeeds.

This blog post barely touches the surface of testing with Capybara. But getting to this point was a great accomplishment for me, and writing the rest promises to be easier with the help of documentation.

My day hacking Google QPX Express airfare API

qpx express When my classmate and I previously attempted to use the Google Feed API for our group project, I have realized that Google documentation is not great for “beginners,” in our case inexperienced developers. It seems to be simple in theory, make a HTTP post request to this url 'https://www.googleapis.com/qpxExpress/v1/trips/search' with json in the request body. But the learning curve is high and here are the struggles I’ve gone through:

1. API key setup: I think this is worth mentioning because the page to do this isn’t straight forward. Sign into Google developers console, click on the project/app => APIs and Auth => Credentials => Click on the Credentials tab. Here you can add and remove API keys.

3. Ruby wrapper: My mentor suggested that I could use Google’s Ruby wrapper for the API so I can make the request server-side. I was able to find documentation on how to create the API client (which is common to all of Google’s APIs). BUT there is one line of documentation specific to QPX, and I couldn’t figure out how to specify the request body so I gave up.

3. 403 “Access not configured”: I put my API key in the header as instructed but was getting this error. It was a combination of 2 things. I solved my problem but didn’t know which fix did it.
+ Initially I had specified under allowed IP the IP address of my apartment’s internet access but I was working from another one. This post suggests that you have to register your v6 and not v4 IP. I don’t even know what that is so I just leave it blank as one post recommends to allow requests from any IP.

+ Still getting the error. I had to restart my rails server and it changed to a 400 status code.

3. 400 “Bad request”: I was fumbling for a while because I didn’t know how to investigate what went wrong. Luckily going under the Network tab (Chrome developer console)
Parse Error. This API does not support parsing form-encoded input

With the help of this stackoverflow thread, I set contentType: 'application/json' in my ajax request.

4. 200 with empty response body: for a while I got a 200 status with nothing in the response body. Even more unhelpful than the two previous errors. I don’t know why this went through, but I started hitting the API and encountered 400 again.
Update: According a commenter, empty 200s happen when using AA or DL as preferred airlines. You need specific approval from those airlines in order to get the information.

5. 400 “Parse error”: This error is similar to the third one but I figured the cause was different because of the different message. It was a bit vague and difficult to search for but I finally found this thread that nails the problem in the head. My json was not really json but a javascript object, very close but not really. I had to simply use JSON.stringify(object) to turn it into valid json. The reason I was so slow to figure out this issue (nearly 1 hour) is because a) I’ve mainly used the opposite method, JSON.parse to read response body and rarely done a post request with such a big request body; b) I’ve mostly made ajax requests to my own Rails server, which accepts an object with no problem.

The “victory” wasn’t that great but it was really, really worthwhile to get back the response object in the console since I’ve spent all day hacking this API with basically no help. I guess I helped myself to Google and Stackoverflow.


From Fashion to Tech

The past three months has changed my life drastically. I decided to abandon my uninspiring marketing job to come to the Web Development Immersive boot camp at General Assembly. I knew the course was going to be challenging but I had no idea how and how much it would change me until it happened.

I will not lose my interest in fashion and design but I’ve developed a new obsession in the name of coding. Every day, every hour, learning, coding, terminal commanding, deploying, trouble shooting, debugging…. Lots and lots of debugging.

I wouldn’t say the course has made me “smarter”, though it did equip me with a lot of knowledge. The most important aspect of this experience is that it helped me fulfill my Potential, something I have always had. Since this is still a fashion blog, I’m posting link to my first-ever web application that I built with Ruby on Rails:

 Note to self: Heroku restart will reveal a lot of errors otherwise hidden.