Geeking Out

I always secretly knew I was a geek. It might have something to do with the math and science classes that I was inherently more interested in back in school. Or maybe it was because of the thick glasses I wore up until high school that clued me in. Little did I know the nerd chic would be a thing. Didn’t see that one coming. Plus, I’m a dancer, a loud laugher, and as quick tempered as they come. So like a good Asian American girl, deny, deny deny. No, I can’t be a nerd like the rest of the asians Hollywood depicted. But it’s come to my attention that I can’t hide it anymore. Last week, I had the honor of being attending Google I/O 2013 conference and of course, there was some swag to be had.

With my new toy sparkling in my mind’s eye, I spent the morning looking up ways to run Ubuntu on my new Pixel Chrome Book. With glee, I carefully saved each web article into my well labeled Evenote system. Reading through every post at work, I skipped home to transform my Pixel into my main development box. In order to get around the fact that the Pixel gives you limited terminal access and your favorite text editor isn’t supported, you can boot the machine up in developer’s mode.

After careful consideration, I decided to go the route of using an Ubuntu chroot. Crouton, Chromium OS Ubuntu Chroot Environment, allows me to have both the Chrome OS and Ubuntu OS up at the same time. This way I can toggle between the two. However, it’s not a true Ubuntu virtual machine. On the flip side, Crouton saves me much needed memory space. Thanks to Brenton Simpson and his script, I am ready to rock and roll on my new Pixel!

For those of you new to Ubuntu machines, here are some helpful tips:

  1. Copy and Paste shortcut keys: Ctrl + Shift + C Ctrl + Shift + V
  2. If Vim isn’t your thing, try nano. sudo apt-get install nano
  3. When you add-apt-respository, don’t forget to apt-get update.
  4. This isn’t specific to Ubuntu, but if you ever find that you need to go to the beginning of the line to edit something, and the left arrow is just too slow, Ctrl + A will get you to the front of the line. Ctrl + E gets you back to the end.
  5. And lastly, here’s a great article with more Terminal shortcuts that every developer needs to know.

Learning About SSL the Hard Way: Recent RVM Installation Error

Does this error look familiar? If you happen to be reinstalling RVM onto a new computer or virtual machine, this error might have popped up. So what gives? My co-workers, @jonzeper and @ctruelson, figured this one out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[2013-03-15T15:42:22+00:00] INFO: Processing rvm_default_ruby[ruby-1.9.3] action create (rvm::system line 183)

================================================================================
Error executing action `create` on resource 'rvm_default_ruby[ruby-1.9.3]'
================================================================================

NoMethodError
-------------
private method `chomp' called for nil:NilClass

Cookbook Trace:
---------------
/tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/libraries/chef_rvm_string_cache.rb:77:in `canonical_ruby_string'
/tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/libraries/chef_rvm_string_cache.rb:50:in `fetch'
/tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/libraries/chef_rvm_string_helpers.rb:55:in `normalize_ruby_string'
/tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/providers/default_ruby.rb:26:in `load_current_resource'

Resource Declaration:

---------------------
# In /tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/libraries/chef_rvm_recipe_helpers.rb

182:         # set a default ruby
183:         rvm_default_ruby opts[:default_ruby] do
184:           user  opts[:user]
185:         end
186:

Compiled Resource:
------------------
# Declared in /tmp/vagrant-chef-1/chef-solo-1/cookbooks/rvm/libraries/chef_rvm_recipe_helpers.rb:183:in `install_rubies'

rvm_default_ruby("ruby-1.9.3") do
  retry_delay 2
  retries 0
  recipe_name "system"
  ruby_string "ruby-1.9.3"
  action :create
  cookbook_name :rvm
end

[2013-03-15T15:42:22+00:00] ERROR: Running exception handlers
[2013-03-15T15:42:22+00:00] ERROR: Exception handlers complete
[2013-03-15T15:42:22+00:00] FATAL: Stacktrace dumped to /tmp/vagrant-chef-1/chef-stacktrace.out
[2013-03-15T15:42:22+00:00] FATAL: NoMethodError: rvm_default_ruby[ruby-1.9.3] (rvm::system line 183) had an error: NoMethodError: private method `chomp' called for nil:NilClass

Your computer connects to https://rvm.io. As of 3/15/13 at 1:20pm, the site has an expired SSL certificate! You can proceed anyways, but this error prevents your computer from automatically downloading and installing. No worries! There is a fix until @wayneeseguin updates their SSL certificate.

If you’re using vagrant, edit your cookbooks/rvm/attributes/default.rb file. There should be some lines that look like this:

1
2
3
4
5
# system-wide installer options
default['rvm']['installer_url'] = "https://get.rvm.io"
default['rvm']['branch']  = "stable"
default['rvm']['version'] = "head"
default['rvm']['upgrade'] = "none"

Change it to this:

1
2
3
4
5
# system-wide installer options
default['rvm']['installer_url'] = "http://get.rvm.io"
default['rvm']['branch']  = "stable"
default['rvm']['version'] = "head"
default['rvm']['upgrade'] = "none"

Ok, but what does SSL even mean? Why do we need SSL certificates? I recently ran into this issue because the native Android web browser didn’t like our SSL certificate. So this is not just an RVM problem. Here’s an oldie, but goodie from youtube explaining it in detail.

The Fashion Hackathon: Lessons Learned

Sponsored by Condé Nast, this hackathon was about bringing fashion together with hackers. I did not officially join a team, but was able to help contribute code during the wee hours of the night. Not bad for my first hackathon! Plus, what went down this weekend was a microcosm of an early stage startup: hash out an idea, build the product, pitch and sell!

For the newbie coders contemplating if they should sign up, here are my takeaways.

  1. People need you. I don’t care how hesitant and insecure you are about your skill level. You are desired. Keep in mind people are building prototypes in 36 hours, nothing fancy. Even a newbie can contribute, have fun and learn.
  2. Meet your community. Ever wonder where the passionate tech people with entrepreneurial minds hang out? Hackathons. Networking? Do it there. Single and looking? I know someone who met his girlfriend at a hackathon. Yup, hackathons are not just for dudes. 40% of participants at Decoded Fashion Fashion Hackathon were women.
  3. Do something new. Feeling bogged down at your job? Sick of tweaking that website for the billionth time? Don’t let those feelings chip away at your passion for coding. Hackathons get your adrenaline pumping and remind you how awesome it is to build.
  4. Assemble a team beforehand. Coding with people you have worked with gives you a tremendous advantage.
  5. Try to tackle the problem and brainstorm solutions beforehand. The first team I joined went through three ideas and disbanded after 4 hours because we couldn’t move forward with anything.
  6. Bring snacks/water/comfortable clothes. Even if they provide food, it’s usually not enough or unhealthy. You may or may not sleep that night.
  7. Practice that pitch! Teams had 2 minutes to present. You should present the problem, the concept of the solution, and quickly demo.
  8. Use the API’s the hackathon are promoting. It’ll make your app snazzier and you could win cool swag. Plus, I think the judges are looking for it.

Seeing how much fun I had, this won’t be my last hackathon.

Landing the Job

Source: etsy.com via Miya on Pinterest

Tomorrow, I start my first job as a software engineer at Conde Nast. I’ll be part of a small, independent team within the company, building a brand new online video platform. It’s promised to attract high traffic almost from day one. Needless to say, I’m thrilled with the opportunity and what’s to come for my own coding skills. And yes, they are still looking for talent. Email me at li.ouyang@gmail.com for more details.

For those of you who have read my previous post, How I Learned to Code in 8 Months, you may remember that I knew next to nothing before I started this journey. It just goes to show how far determination, time and commitment can take you. Good luck to everyone in their own endeavors!

What Is a N + 1 Selects Statement?

No one wants their applications getting all chubby and slow. Even if chubby can be cute.

From several different people, it’s been made clear to me that how you query your database will greatly affect the speed of your application. A particular problem that I learned about is the n + 1 selects statement. Don’t get confused with Big O notation because it’s entirely different. This is more specific to how SQL queries data.

Specifically in join statements, you may find yourself falling into the trap of writing n + 1 selects statement, when it can simply be just one select statement. In my application, a yoga_class object belongs to a yoga_teacher. In order to try to find yoga classes that are taught by teachers which have a certain attribute, I first did this:

1
2
3
4
5
6
7
8
9
013:0 > YogaClass.all.collect{ |yc| yc if yc.teacher.favorite == true }.compact
  YogaClass Load (4.0ms)  SELECT "yoga_classes".* FROM "yoga_classes"
  Teacher Load (0.2ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 31 LIMIT 1
  Teacher Load (0.1ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 32 LIMIT 1
  Teacher Load (0.2ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 39 LIMIT 1
  Teacher Load (0.4ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 32 LIMIT 1
  Teacher Load (0.2ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 102 LIMIT 1
  Teacher Load (0.2ms)  SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = 37 LIMIT 1
  .......

My terminal spit out a long line of select statements, which I’ve omitted most of. It makes the first select statement, which corresponds to our ruby YogaClass.all. Then the long list of other select statements is iterating over all the teachers of the yoga classes. This is our classic n + 1 selects statement. The 1 represents your first query, which returns a subset (in my case the whole table). The n represents a select statement for each row in the subset.

Not very efficent. How do we get around this? ActiveRecord provides finder methods called joins that act like JOIN clauses in SQL.

1
2
3
017:0 > YogaClass.all(:joins => :teacher, :conditions => { :teachers => { :favorite => true } })
  YogaClass Load (0.9ms)  SELECT "yoga_classes".* FROM "yoga_classes" INNER JOIN "teachers"
  ON "teachers"."id" = "yoga_classes"."teacher_id" WHERE "teachers"."favorite" = 't'

Here we only have one select statement, making everything, cleaner, faster, and easier for our database.

Creating Dynamic Link Helper

As I’m working on my yoga project with @robert_beene, I’m still stuck on deciding how to display classes. For now, I’m only showing classes one day at a time, deciding against a cluttered google calendar type view. However, what about if someone wants to see classes for another day?

In order to attain uniformity, I added this line of code to my routes.rb file.

1
match "/yoga_classes/:year/:month/:day", to: "yoga_classes#show_class"

Segments starting with colons are called dynamic segments, and allow your rails app to have access to them through params.

In my yoga_classes_controller.rb, I created a non CRUD action, show_class. Notice how I’m pulling the date through params.

1
2
3
4
5
6
7
8
9
10
  def show_class
    date = Chronic.parse("#{params[:month]}/#{params[:day]}/#{params[:year]}")

    @todays_yoga_classes = YogaClass.fav_classes_on(date)

    respond_to do |format|
      format.html  { render 'index' }
      format.js
    end
  end

Now in the view, I wanted to create a link to the next day’s classes. But depending on what page I’m currently on, the next day’s classes would always be different. So I came up with this helper method in yoga_classes_helper.rb.

1
2
3
4
5
6
7
8
  def link_to_next_days_classes(description)
    if params[:day]
      date = Chronic.parse("#{params[:month]}/#{params[:day]}/#{params[:year]}").tomorrow
    else
      date = DateTime.now.tomorrow
    end
    link_to description, "/yoga_classes/#{date.strftime("%y")}/#{date.strftime("%m")}/#{date.strftime("%d")}"
  end

Now, in my templates, I have access to this new method! In my index.html.erb I can use link_to_next_days_classes("Next Day") anywhere I want now. Any ideas of a more elegant way of doing this? Would love to hear it.

4 Lessons From My Job Search

As I’m focusing on the job search lately, it’s taken me away from coding, but I’d like to share my thoughts on this part of the journey.

  1. Treat each potential job opportunity as unique. I know some advocate that finding a job is a numbers game and like marriage, you only need one to say yes. As a web developer in NY, there are enough choices and demand to not just play the numbers game. Plus, the more effort you put into finding the right job and believing that it’s not just a paycheck, but a career, the more likely you’ll be happy.
  2. Talk to as many people as possible. Whoever says they know what they want is deceiving themselves. Humans are great at this. The more people you talk to, the more information you can attain, the better decision you can make.
  3. Trust your gut instinct if you’ve done your research. Nobody on earth knows you better than you do. So if something inside of you sounds like alarm bells going off, listen to it. You need to be able to trust your future employer.
  4. Don’t be afraid to take risks. I go by the motto that you’ll never know until you try. Plus, the worst case scenario is that you don’t like something, and you start the process again.

Although I have not yet secured that dream job, it’s safe to say that I’m excited by the opportunities that lay before me. Flatiron School has even set up a happy hour for us to meet with more start ups from WeWork this Thursday!

Resources to Get Started With RSpec

Time to get over my hesitations with testing. As I work on Yoga in the City, I’m going to do my best to code TDD style. Here is a list of resources that I’ve been using to get started. Would love to collect your suggestions as well.

  1. Code School’s Testing with RSpec is a good introduction.
  2. Everyday Rails Testing with Rspec does a good job walking you through many examples and usage with Factory Girl.
  3. Better Specs. They describe their tests differently than Everyday Rails Testing with Rspec. Better Specs describes each test with the name of the method, versus describing what it does. Not sure which way I should go with.
  4. Rspec Best Practices.

Will be adding to this list!

Caching Fragments

In order to speed up performance, sometimes you’ll want to cache a page. Once the data changes, the cached page should expire, in order to show the new information. Rails has some features built in to help us with this. One of which are Sweepers. The Rails API claims this:

Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change. They do this by being half-observers, half-filters and implementing callbacks for both roles.

[Rails API]] [http://api.rubyonrails.org/classes/ActionController/Caching/Sweeping.html] [ActionController::Caching::Sweeping]

However, much to my dismay, if an object was edited or created outside of the controller, the sweeper doesn’t seem to pick it up, despite the Rails documentation. This means cron jobs or objects created/edited in console doesn’t trigger the sweeper, and you’re left with stale cached pages. After digging through many stackoverflow threads, like this one, it seems like I wasn’t the only one to struggle with this.

However, I did find a workaround: fragment caching! Thanks to Ryan Bates for another great railscast.

Modify the configuration file and set perform_caching = true.

/config/environments/development.rb
1
config.action_controller.perform_caching = true

To cache a fragment of any view, simply wrap the code with <% cache 'something' do %> <% end %>. The fragment will be cached with whatever you want to call it. Let’s say you want automatic expiration. You can do this by replacing 'something' with something like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<p id="notice"><%= notice %></p>
<h3><%= @mixtape.name %></h3>
<table class="table table-bordered table-condensed table-hover">
  <tr>
    <th>Song Title</th>
    <th>Genre</th>
  </tr>
  <% @mixtape.songs.each do |song| %>
    <% cache song do %>
      <tr>
        <td><%= song.title %></td>
        <td><%= song.genre %></td>
      </tr>
    <% end %>
  <% end %>
</table>

Automatic expiration works here because of key-based expiration. Check it out by going to console and typing in song.cache_key.

1
2
3
4
5
6
7
8
9
001:0 > song = Song.first
  SCHEMA (3.4ms)  PRAGMA table_info("songs")
  SCHEMA (0.2ms)   SELECT name FROM sqlite_master WHERE type = 'table' AND NOT name = 'sqlite_sequence' AND name = "songs"
  SCHEMA (0.1ms)  PRAGMA table_info("songs")
[DEBUG]   Song Load (1.1ms)  SELECT "songs".* FROM "songs" LIMIT 1
  Song Load (1.1ms)  SELECT "songs".* FROM "songs" LIMIT 1
=> #<Song id: 1, title: "test", created_at: "2012-12-31 17:43:25", updated_at: "2013-01-02 10:37:58">
002:0 > song.cache_key
=> "songs/1-20130102103758"

The cache_key is updated through the updated_at timestamp. So the line <% cache song do %> checks to see if there is a fragment that is the same as song.cache_key. If not, it generates a new one, and expires the old one. More information about cache keys from DHH himself here.

One thing to be careful of is the naming of fragments. If you’re caching on multiple templates, chances are you might accidently create a fragment with the same name. To get around that, prepend a string by using an array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<p id="notice"><%= notice %></p>
<h3><%= @mixtape.name %></h3>
<table class="table table-bordered table-condensed table-hover">
  <tr>
    <th>Song Title</th>
    <th>Genre</th>
  </tr>
  <% @mixtape.songs.each do |song| %>
    <% cache ["available", song] do %>
      <tr>
        <td><%= song.title %></td>
        <td><%= song.genre %></td>
      </tr>
    <% end %>
  <% end %>
</table>

In our case, song belongs to a mixtape. So in the song.rb file I’ve added a touch: true to the association, to ensure the associated model, mixtape, gets updated everytime the song gets updated.

1
2
3
class Song < ActiveRecord::Base
  belongs_to :mixtape, touch: true
end

While you’re testing caching, you may notice your changes not going through. Be sure to Rails.cache.clear everytime you change the code regarding caching. Interesting? Read more about advanced caching here.

How I Learned to Code in 8 Months

When many people look at my resume, they’re often confused by my drastic career switch. They’re also confused by how much I’ve learned in the past 8 months. Considering I barely knew how to use a Mac in the beginning of this year, I’ve come a long way. I still remember being asked to “Command T” at the command line, and literally typing those words out. But if I can learn how to code, so can anyone. Here are my tips and tricks.

  1. Time. This is the number one thing you will need. It’s easy to be distracted, but if you want to learn how to code, commit yourself.
  2. Online videos. My favorites are Code School and Ryan Bate’s amazing Railscasts.
  3. Reading books. At the end of the day, books still have the most in depth explanation. My favorites are Eloquent Ruby and Practical Object-Oriented Design in Ruby. There’s a difference between hacking something together and knowing why it works.
  4. Start building. Even with little of knowledge, Rails makes it easy to start programming and learning on the way. Within 2 months of learning how to code, I met someone to build our own mood tracker app, called Floating Journey. Building something gives you the motivation and inspration to push further. It also quickly points out the holes in your knowledge.
  5. Community. Having people to learn with is like having a work out buddy. Someone is there to share your struggles and also hold you accountable. As you immerse yourself in a community, you’ll learn faster and maybe even find yourself a mentor.
  6. Blogging. Articulating my thoughts forces me to clearly think through each topic. It’s also serves as a nice reminder of all the progress I’ve made.
  7. School. This is the ultimate choice. I dedicated 3 months, 40+ hours a week to attending Flatiron School, where I learned how to code, side by side, with 18 other classmates. It took a massive amount of commitment (time and money), gave me a community, access to a teacher, and so much more. My time at Flatiron accelerated my learning process exponentially.

Happy New Year! May 2013 bring as much joy as 2012 did!