SEO: What Developers Need to Know

by Dan DeMeyere - @dandemeyere

SEO has amassed a bad reputation over the years. Is it legit? Is it snake oil? The truth lies somewhere in the middle. SEO can improve the quantity and quality of organic traffic you receive, but it's not magic. The SEO 'specialists' who suggest building link farms, low-value landing pages, and other shady techniques designed to game PageRank (Google's ranking algorithm) are largely to blame for the negative SEO stigma, but SEO is real and it is valuable.

While there are legitimate SEO professionals who can add value to your website, no one person or department should be solely responsible for SEO. SEO should be a team-wide effort.

Education, authenticity, and diligence should be at the core of this effort. Product, marketing, and development teams should all be educated on SEO and its best practices. It's up to these teams to ensure that the SEO techniques implemented are in the best interest of the user (authenticity) and that the SEO efforts are a continued focus during the construction of your website (diligence).

I recently presented my research and thoughts about SEO to our entire team at thredUP . While the presentation ( click here to view it ) was tailored to a non-technical audience, my focus in this post will be on what developers need to know about SEO.

Google PageRank

It's important to prioritize your development resources to yield the biggest SEO gains for the smallest amount of development effort possible (aka leverage). The first step is to determine your organic traffic breakdown by search engine source. If you're like us, Google is probably your #1 source (over 95% of thredUP's organic traffic comes from Google). Because of this, you should focus on optimizing towards Google's search result ranking algorithm PageRank.

Regardless of whether you're a developer or not, I believe a basic understanding of how search engines work is all that's required to be effective with your SEO efforts. Based on what Google has released themselves and from what other websites have tested and documented, there are widely known and accepted factors that play into Google's PageRank algorithm.

Discovery

Google has to be aware of your website's existence and the content you offer before PageRank can evaluate and index it. Here are some ways to ensure Google finds your content:

  • Manual submission - through Google Webmaster Tools, you can directly add your URL to Google's index .
  • Backlinks - when websites other than your own link to your website and its content, it will provide Google's crawlers another way to discover what your website has to offer.
  • Sitemaps - an HTML/XML file that lists every link you want Google (or your user) to know about on your website.
  • Structured linking - having an organized flow of links on your website allows Google's crawlers to more easily traverse your website and understand the relationships between the content on your website through your links.
  • Product feeds - if you're an e-commerce website, you can send Google your inventory along with meta information through their Google Merchant account center to help ensure what you're selling is showing up in Google search/shopping results.

SEO Elevators

There are certain things that will elevate you above others in Google search results.

  • Quality content - unique and genuine content trumps everything (ex: Wikipedia's quality of content is the reason why they are #1 in search results for almost everything). Google only cares if you're providing value to the user so if a user clicks on a search result and immediately clicks 'back' because the page wasn't helpful, Google knows and it will lower the ranking for the page.
  • Backlinks - the more websites that link to yours, the better your search rankings will be; however, the quality of the backlink is important as well. If a well-known and respected website links to your website, they are legitimizing your website through their own website's PageRank credibility. Conversely, if a small website that is relatively unknown links to your website, the benefits will not be substantial.
  • Best coding practices - being HTML compliant (ex: using alt attributes for images, title tag text for links, etc.), using a hierarchy of HTML elements (h1 tag for page header, h2 tags for sub headers, etc.) and building descriptive URL schemes will further enhance Google's ability to add context to your website's content as well as signal to Google that you take care in the construction of your website.
  • Keywords - if you know the main keywords people are using in their Google search queries for your website, which you can view inside Google Analytics, you can then tailor your meta information content around those keywords to further emphasize their importance.
  • Speed - Google knows how long your page takes to load (Google Analytics) and they know users don't like to wait so the speed of your website will impact your ranking.
  • Usability - Does your website need JavaScript to work? Do you have too many ads? Is your layout conducive to a good user experience? Google's latest PageRank updates include the ability to load JavaScript and CSS to analyze the layout and usability of your website.

SEO Detractors

In general, if you don't follow the best practices mentioned in the list above, you're going to detract from your website's SEO potential. However, there are some things you can do that Google will penalize you for if they find out you're doing. If you want to see an example of how serious Google's penalties are, click here and once the slide loads, click 'i' on your keyboard.

To avoid Google PageRank penalties, stay away from these SEO tactics:

  • Keyword stuffing - if you embed too many keywords into your website's meta information HTML tags, Google will have a tougher time deciphering the signal from the noise. If you really abuse the use of keywords, Google can penalize you for intentionally trying to game the system.
  • Cloaking - putting scrape-able content on a page, but hiding it in from the user is a big Google 'no-no'. Google can load the CSS on your website so they know what content is visible to the user and what you're hiding from them.
  • Low-value pages - creating hollow pages that don't provide a lot of quality content to the user. This is also known as 'content farming'. Good for traffic, but bad for the user. If you create keyword landing pages, make sure you're providing value to the user.
  • Link farms - if you try to 'game' the number of backlinks your websites has by creating new websites that link back to your original website, Google will find out and it will hurt your page ranking.
  • Plagiarism - if you use other people's content, Google has ways of detecting who the real author is and they can issue page ranking penalties if you claim the content as your own.

SEO Summary

Users come first. Google's search engine is designed to give users the information they're looking for as fast as possible. Google doesn't care about your website, it's all about the user so make sure you're building new features for the user and not building features to attract more organic traffic. If you build a genuinely great product for your users and follow best SEO practices while building it, then you'll see results in your organic traffic. Here are some guidelines to follow why you're building your product:

  • Define & communicate keywords - determine what keywords perform best for your website and communicate them to your development team so they know what meta information to focus on (i.e. page titles, meta descriptions, alt text, etc.).
  • URL Naming - take URL naming seriously! Grab a developer and bounce naming convention ideas off of them. When you change a URL at a later date, it hurts the page's SEO juice. 10,000 backlinks to one link is greater than 5,000 backlinks to two different links that end up at the same page. Think about it.
  • Quality content - the copy/content on a page matters. Copy and pasting is the devil for SEO. Be creative, take your time, and make it count.
  • Sitemaps - are you adding a new feature? Make sure you add the appropriate links to the HTML & XML sitemap. Make sure you have FAQ content in place.
  • Don't be lazy - have an image? Make sure there's alt text. Have a link? Make sure there's title text. Use the right elements (h1, h2, p, etc.).
  • Think hard on the meta - when you place the alt text, make it meaningful. If you care, you'll take the time to do it right.
  • JavaScript beware - if a link requires jQuery to work, you're doing it wrong. If a bot can't get from page to page, you're doing it wrong. Disable JavaScript and load your website, the content you want indexed better still be there.
  • Plan from the beginning - before you start coding, think about SEO. SEO can dictate execution (i.e. don't bring content in via AJAX).
  • Natural feature flows - does the feature flow intuitively? Is it organized? Is there a hierarchy? Can you a build a directory page for it?
  • Don't be shady! - Google doesn't like it. Developers don't like it. It feels dirty-all-over to code something that does not benefit the user and has negative, ulterior motives.

If I missed anything or you disagree with my conclusions, please comment below.

Upgrading Rails from 3.0 to 3.1: What the Guides Don't Tell You

by Dan DeMeyere - @dandemeyere

We upgraded the thredUP app from Rails 3.0 to Rails 3.1 this past week. On the day we deployed the upgrade, our test suite was green and everything looked solid locally and on our staging server, but out of sheer paranoia I decided to take one of our front-end servers off of the load balancer and deploy to it so I could poke around on the Rails production environment....and then a bit of chaos ensued.

There are some aspects of a production environment that can't be replicated in your test suite and can't be invoked locally. A good example of this is SSL. Did you know that `ssl_required` was deprecated in Rails 3.1? I didn't (here's the solution btw). Then there are production-only gems to worry about (ex: monitoring services). New Relic's gem required a bump for Rails 3.1. And by required a bump, I mean the gem caused the entire app to crash with a cryptic error message. Fun!

You're probably thinking that this upgrade lacked preparation. Quite the contrary. Before I started the upgrade, I read guide after guide about upgrading to Rails 3.1. Because we wanted to upgrade in phases, I wasn't interested in the asset pipeline requirements, but it seemed as though that was the only thing every guide was focusing on. What the guides weren't focusing on were all the gems that would have to bumped (and their dependencies) and what the ramifications of those bumps would be. ActiveRecord, Cucumber, and PayPalNVP were a couple gems in particular that had noticeable changes that deserved some love in the upgrade guides. So that's what this post is, some love for the not-so-obvious deprecations that should give you clearer expectations of what you'll be running into when upgrading to Rails 3.1.

Active Record

Condition hash syntax is on it's way out. It's been fully deprecated from named scopes and the `find()` method.

Another big gotcha is 'include_root_in_json' being defaulted to false for every model now. Here's the difference:

Small difference between the two, but if all your JSON responses previously had the root included and you have external apps (iPhone, Android, etc.) relying on your app's internal RESTful API (like we do), then it's a significant difference as it's possible all those API endpoints will have to changed or the apps will break. So how to change this? Below I'll demonstrate how to set an app-wide default and then how to override the setting in individual models.

Gem Bumps

Almost every Rails app relies on a myriad of gems. Including our development and test environments, thredUP uses over 50 external gems and a handful of our own private gems we've created over time. When we upgraded from Rails 3.0 to Rails 3.1, there were some notable gems that required version bumps.

There are some big boys in there (ex: mysql2 is our MySQL adapter). If you use any of the above in your app, which I'm betting you do, make sure to take note of their version bumps

PayPalNVP

If you use the PayPal NVP gem, expect to make some changes. The biggest for us was that the PayPal NVP API requires all authentication upon object instantiation. Example:

If you do full 3rd-party API mocking in your test coverage, you could see how this change would be problematic.

Lastly, make sure to read the Rails 3.1 release notes or Ryan Bate's gist of 3.1 RC4 changes. That's where some of the standard Rails-only deprecations will be. The biggest one to note - all forms (or any Rails view helper that results in HTML being outputted into the source) requires a `=` instead of `-`. It's a simple change, but if you use a hyphen on accident, nothing is outputted to source and it can be quite confusing to debug since no errors will occur and nothing is in the HTML.

If you came across any unique errors when you upgraded your app to Rails 3.1, please mention them below in the comments and I'll update the post afterwards to include them.

Refreshing Web Design Trends

by Dan DeMeyere - @dandemeyere

In the past year, the post 2.0 web design era has really come into its own. I wrote about the start of this when web designers first started to embrace HTML5 and what it has to offer, but the time has finally come when over-the-top Flash websites, such as this one, are no longer the standard for those that are pushing the envelope for creative web designs.

Here are 4 websites who have utilized HTML/jQuery and creativity to build refreshing designs:

SlaveryFootPrint.org

Go to SlaveryFootPrint.org. It's ok, I'll wait for you to actually click the link. Once the page loads, you'll notice you have two options. Click the first one titled 'What? Slaves work for me?'. Now start scrolling. Killer, right? With a little bit of jQuery and some clever CSS, this website is re-inventing the way to deliver information to users. Lines of text are brought in at the same pace as your scrolling, allowing you to control how quickly you want to read their text. On top of this, they have different graphics pushing the text into place to make the reading experience fun.

JamesAnderson613.com

A lot of freedom is granted when designing a personal website. It can say anything and look as wild as you want it to look. Shockingly, one of my favorites is not a designer or a developer's website - it belongs to a cricket player. James Anderson's website is awesome and it's showing off one of my favorite trends: making numbers sexy on the web.

HTML5, specifically the addition of Canvas and SVG, has given designers free reign to design graphs, charts, and other data visualizations without having to worry about how they will be built. Thanks to JavaScript libraries like D3.js and Highcharts.js, developers no longer have to worry about Flash or any other antiquated plug-in for interactive visuals. And while D3/Highcharts are two of my favorites, there are plenty of other emerging solutions.

Tangent: if you're someone who is looking to make your own website, I strongly recommend you look over this Quora list of best personal websites on the web.

DIY.org

DIY.org is a very cool website. It's a kids website that highlights really cool things that kids and parents make and it's also showcasing the last trend I'll mention in this post that I'm excited about - high powered web graphics. In the past, image sizes were always a huge cause for concern because of bandwidth limitations and costs. As broadband internet becomes more prevalent and static asset storage (ex: AWS S3) becomes more and more affordable, image sizes become less and less of a concern.

When you go to the DIY homepage, you're presented with a stunning graphic. After a couple of seconds, the text overlays disappears and you're able to grab the graphic and move it to explore (with a nice easing effect to simulate gliding). The entire graphic is larger than 3000x3000 pixels, but through some clever coding the actual images that compromise the entire graphic are 35 387x387 image tiles. I would also bet good money that only the necessary tiles are loaded until you try and explore surrounding tiles. The reason why I think this will become a web trend is because this same high-quality graphic tiling technology could be used for a web-based video game built on top of HTML5. A 'level' in the game could be hundreds of thousands of pixels, but when the graphics are loaded only when needed, it could be realistically done with ease.

DangersOfFracking.com

This last website is a combination of all three trends I mentioned: re-inventing the way to deliver information, beautiful metric visuals, and high powered web graphics. By utilizing all three, the creator of this website was able to bring to light a very serious topic (Hydraulic Fracturing) and deliver the information on the topic to you in such a compelling way that you want to learn. You need to keep scrolling. They have gamified the process to digest information on the web. It's brilliant.

JavaScript Namespaces

JavaScript is a mess. Well it can be, and it certainly used to be once upon a time. I believe the biggest problem is that there are so many ways to write JavaScript, that finding "the best way" is nearly impossible. Doing so while working in a team with variable JavaScript experience is that much harder.

Here are some examples of how different people might code the same behavior:

The Worst

This style has been dead for a long time (phew), mostly thanks to the arrival of Prototype, jQuery and the other major JavaScript libraries. However, we still see a lot of "floating" function definitions of this type. This is scary for 2 reasons.

  1. It is difficult to find semantically related code. For example: baz() might handle something entirely different from foo(), forcing you to scroll around looking for one or the other.
  2. You might be overwriting something from another library (or vice versa).

The second point is the one I'm targeting in this post. What would happen if I were to include a second JavaScript file with a separate function also called bar()? The first implementation would be blown away by the second one.

A Better Approach

Wrapping JavaScript objects is a better approach. This time, we can have a more meaningful name to separate a block of code. But there's still a small possibility that this could break! What if I downloaded some cool new JavaScript library the next day to handle something else, but it just happens to have an object named stuff that it needs in order to work correctly? Things would explode!

This calls for extreme namespacing!

Don't Be Afraid to Make Things Longer Than You Might Think They Have to Be

Mmmmm names! Here I create a thredup object that will store all things thredUP. Normally, I would put the thredup = {} in a separate file that would always be included first (kind of like jQuery). You might even put some stuff in the definition, like standalone utility functions or useful "static" variables. Now we have to refer to our stuff object via its full name, thredup.stuff. It should live in its own file called thredup.stuff.js. This ensures that the only way to "accidentally" overwrite something is by not looking at the JavaScript includes (which never happens, right?).

I do a lot of other crazy things in this snippet. I use a self-calling, anonymous function and pass the thredup object right in. I do this just in case we're going to add more than one object to thredup that might need to share data through closure.

The function for stuff creates an object that I call self which represents the "true" object. This allows me to have private members. The variable foo is passed in as an argument. I then create a new var foo and assign it to the value passed in. This ensures that the local copy of foo is set for the rest of the closure. Every method that I go on to define will have access to that foo, but foo cannot be accessed outside of the class, as in line #29. This is also true of privateMethod(). I didn't stick it on the self object to keep it private. The thredup.stuff function then returns the self object, which exposes the functions bar and baz.

Huh?

JavaScript can get a tad confusing, especially when we stretch it to its limits, but I think writing objects and widgets this way leads to cleaner, more legible code. I also think it's a little easier for someone to grok coming from a more tradional OO language (self.foo => public, var foo => private).

Please feel free to ask questions in the comments, I'd be more than happy to answer them.

Chrome Developer Tools Tricks & Tips

by Dan DeMeyere - @dandemeyere

If you're a web developer and you have spent time writing JavaScript and/or styling with CSS, odds are you're familiar with Chrome Developer Tools (CDT). When I discovered CDT, my front-end productivity sky-rocketed. Editing CSS on the fly, inspecting HTML, and interacting/debugging with the page's JS console have become more engrained in my day-to-day workflow than any other development tool I use. I love TextMate, but if someone put a hypothetical development gun to my head and asked me to choose between CDT and TextMate, I would be asking around for good a Vim tutorial if you know what I mean.

Quick disclosure: all of the tricks and tips below have been tested with CDT, but there's a chance they won't work with FireFox's Firebug Add-on.

JavaScript Debugging

There are three very useful tools in CDT to debug your JS. The first is the most obvious - the interactive JS console. When you open up the developer tools (⌘ + Alt + I), the interactive JS console resides with the 'Console' tab. You can also press (⌘ + Alt + J) to dual-load CDT and the console tab. This console allows you to interact with the page's DOM. You can execute any JavaScript you want here and also interact with objects (like the window object or any local objects you've defined) and inspect their contents/functions. One important note is that when this console loads, the DOM has loaded as well, which means if you're using jQuery and it's working on the console, but not in your source file, you're probably missing a jQuery $.ready() wrapper.

The second debugging tool is fairly new to me. If you click on the 'Scripts' tab and choose one of the JS files included in the page, you're able to add breakpoints to the code by clicking on the line numbers. Once the breakpoints are added, you can step through every breakpoint. It can be tedious tracking down the code you want to put the breakpoint in if you have many files. It's especially painful if you're writing in CoffeeScript as the line numbers you're editing in your .coffee file differ from the compiled line numbers of the same .js files (what you see in CDT).

Last week a colleague of mine, Wilson Collado, told me about the 'debugger;' call. If you put 'debugger;' in your JavaScript, it's the equivalent of putting a breakpoint through the scripts tab. It's a really useful trick that can save you a lot of time. One last thing about the scripts tab - make sure you take a look at the call stack information panel (located on the right side of CDT's scripts tab). In this panel you can also inspect all the local variables at the time in which the breakpoint/debugger was reached. Very helpful when stepping through your JS.

I would be remiss if I discussed JavaScript debugging and didn't mention the 'console.log()' function. In your JS, you can pass any object to console.log and it will print out the object on your console when the code is executed. You can then inspect the object to look at its value/properties. Simple, but very useful. In addition to log(), console also has warn(), info(), error() and assert() functions. Assert is really nice as it will evaluate the contents of whatever is passed into the function as a boolean. Beware that leaving in console calls will break your JavaScript in Internet Explorer, so make sure to take them out before you commit your code.

HTML/DOM Tricks

If you right click on any part of a website in Chrome (with the exception to a website built in Adobe Flash), there's an option called 'Inspect Element'. This is any front-end dev's bread and butter. You can view/edit HTML, traverse the HTML hierarchy, view CSS for any HTML element...the list goes on. For the most part, inspecting the HTML is elementary (yes, pun intended), but did you know that if you select an element, go to the console, and type '$0' - the last element you inspected is now tied to that variable? I didn't. Will User dropped that gem on me last week. The $ command dumps previously selected nodes, try typing $2, $3 and so on.

Here's another one that is news to me. There are certain CSS selectors that are used on every custom-styled button (or link). They are ':hover' and ':active'. If you have a button that is supposed to change it's image when you cursor over it or press it, you're invoking one of these selectors. It's a pain to style them though because when you hover over the element, the CSS properties show but you can't edit them without moving your cursor over to the CSS property (it's hard to explain, just try to do it and you'll see what I'm talking about). Enter the 'Toggle Element State' feature. In the CDT CSS pane, click the 'Styles' arrow and then click the button with the dotted square with a cursor in the center of it. Now you can toggle these selectors. See below:

Console DOM Tips

Lastly, let's go over some tips that involve both the console as well as the Document Object Model (DOM). Fire back up that console press (⌘ + K), which will clear the console. Grab an element off the DOM with jQuery (or do $0 if you've recently inspected something). Now call 'dir()' and pass in the element. As you'll notice, 'dir()' will print out every attribute/property that exists for the element. There are definitely some properties I didn't even know existed after using it for the first time.

Let's say you're generating something on the console. Maybe a calculation or you're scraping a page for some text. Did you know that you can pass in JavaScript to the 'copy()' function and it will copy the result of the JavaScript to your clipboard? The potential uses are probably not obvious, but it's another solid tool to keep in that JavaScript debugging toolbox.

If you have some CDT functions/tools/tricks that I didn't list, please share them in the comments.

Design Inspiration

by Dan DeMeyere - @dandemeyere

Being inspired is one of the strongest types of motivation for me. When I see something great, I can become inspired to build something of equal caliber or at least put more effort into what I'm currently working on. Sometimes the execution of an idea can be just as inspiring as the idea itself. One great example of this is Path. The more you use their app, the more you can appreciate how much attention to detail was involved in building the app. Every interaction, every pixel, is perfect. It's hard to put into words the experience that is felt when you use something and everything is just 'right'. 

So just in case you need some inspiration, here are some websites and Dribbble shots that I find inspiring.

www.BlameStella.com

Other than giving thredUP a great score, Stella's website has nice, non-obtrusive color tones that emanate an inviting feeling. It's refreshing to see a website that isn't exploding with 20 call to action buttons.

www.1minus1.com

I love the graphics on this site. A well crafted back-end can be just as important as a pixel-perfect front-end and the illustration of design and development being poured together into a funnel is a great visualization of this.

Fork CMS

When I'm looking to use a new library, gem, or application, I find that the presentation of the product impacts my judgment towards my willingness to give it a try. Fork CMS is a great example of this. There's no reason for me to use a new CMS, but after visiting their website I wanted to download it and try it out anyways.

Dribbbles

Now it's time for a couple of Dribbble shots. This Twitter share shot is particularly awesome for a subtle reason. Twitter makes it very hard to change the style and design of their Tweet button. You can do a custom-designed button that links to Twitter.com, but the user has to leave your website to make the tweet. To allow the user to tweet without leaving your website, you have to use their pre-built button/widget. This person designed around the button, instead of re-designing the button itself, which keeps the best functionality intact while making the developer's job easier.

No explanation needed for this one, I just think it's awesome and would be a really cool login interaction.

I'm not embarrassed to show the inspiration (or exact copy) of my work portfolio design. I was brainstorming the best way to allow users to interact with my professional experience on my website and a colleague of mine sent over this Dribbble. The UI looked so cool that I wanted to code it up just for the fun of it, but I liked it so much that I ended up keeping it.

A lot of these websites were discovered on line25's Websites of the Week series. It's a great RSS feed to follow if you're a fan web design. If you have any websites you would like to share, please link to them below in the comments.

New Additions for your Rails Toolbox

by Dan DeMeyere - @dandemeyere

One of the biggest advantages to using Ruby on Rails as your web framework is the open source community. They unselfishly release new gems every day. They build the best tutorials for free and they commit to the latest Rails builds on a daily basis. The only variable left in the equation when you're building a Rails app is knowing what tools to use when approaching a project implementation. Having a solid toolbox at your disposal is essential to furthering your professional development as it allows you to take on more challenging projects that are outside your comfort zone.

When I first started developing with Rails, I was blown away by my CTO's ability to nonchalantly take on challenging projects. The project or feature would seem outlandish and at times borderline impossible, but he would say something like "we'll figure something out" and somehow he always did. It seemed like magic. After watching closely for many months, I came to realize he had three things: a positive outlook, a solid toolbox, and a creative imagination. The combination of the three were a potent arsenal for tackling epic projects. He wouldn't think about why it couldn't be done - he would start in the ideal world that everything's possible and begin brainstorming from there.

Having a good outlook and creative imagination is not something you can attain from reading a blog post, but you can always add more tools to that handy toolbox. Here are four new additions to my toolbox; hopefully one of these will help you one day when you come across a new project.

Storing your ActiveRecord Objects in Redis

Link to article →

Speed is important. Rails contains a fair amount of overhead and it's considered one of the harder frameworks to scale. It isn't an issue when you're website is small, but as you grow you'll discover some of the earlier code that was written in your app won't hold up as the user base grows. This results in feature re-writes and becoming more clever with your implementation. One of the first tools to reach for when attempting to speed something up (outside of profiling your DB queries) is cacheing. We use memcached at thredUP, but the problem with memcache is that the data isn't persistent. If your memcache server goes down, you can lose all the cached data within it. This makes memcache only feasible for information that can afford to be lost. What about data that needs to be written to the DB? You can't reliably do it with memcache, but you can with Redis.

The tool I linked to above is a gem that the fine folks of Gowalla, recently acquired by Facebook, wrote to accommodate quick writes and reads of an ActiveRecord object. Their example is 'liking' something. You have to be able to like something quickly and pull back information on that like such as how many others have liked it and who they are. Personally I've been wanting to re-write thredUP's in-house notification system for a while as it hits the database on every logged-in page load and this is going to be the first tool I reach for when that time comes.

Converting Dates Between Ruby and JavaScript

Link to article →

This one is very straightforward. In multiple parts of our app, specifically areas of the app we're doing background AJAX polling, our JavaScript scrapes time data off the DOM (like timestamps of objects stored on an attribute of a div). The problem is that JavaScript's time (local) and our server's time (GMT) are in different time zones. The link I listed above will give you a quick and easy way to go back and forth from Ruby's time class to JavaScript time class.

Lazy Evaluation and Method Chaining

Link to article →

Most people know about method chaining in Ruby, especially within the context of ActiveRecord methods. Most people also know that an ActiveRecord call does not hit the database while it's still an ActiveRecord::Relation object, which is an example of lazy evaluation. The real tool comes from using both of these together.

The best example I can give is compound filtering. If you go to an e-commerce website and select 'Sort By: Lowest Price' and 'Gender -> Men', those are options that will compound to filter your results. One way of implementing this is having a nasty 'if params[:sort] = "Lowest Price" && params[:gender] = "Gender"' block for every possible filtering scenario. That is obviously not ideal. But if you were to add some named_scopes that build conditions for each individual filter and method chain all the compounding filters onto a ActiveRecord::Relation object that executes its call to the DB at the end, then that would be a clean way of doing it.

ActiveRecord Key Value Stores

Link to article →

Key value stores are awesome. They're super simple and super fast. To get geeky for a second, searching with key value stores in big O notation have a time of O(1) (that's the fastest). I like to hack together Hash look-up objects in Ruby all the time to speed up checking whether a ActiveRecord ID is in a collection. The alternative is using an array (assuming it can't be looked up in the DB) and even if the array is sorted and the array look-up call is using a simple B-tree algorithm, the notation is still O(log n). You just can't beat key value stores for look-ups.

The link I referenced is leveraging the method_missing method of a class as a way to arbitrarily set key values. I would never use something like this on a heavily used model such as User as using method_missing like that is dangerous, but it does make sense in context of ApplicationSettings. Either way, it's a clever implementation for dynamically setting class attributes and it opens up your imagination for ways in which it can be used.

Have a tool you would like to share? I'd love to hear about it below in the comments.

Facebook FB.ui() apprequests IE Bug

by Dan DeMeyere - @dandemeyere

That title was a mouthful! This post is a simple bug fix for an IE 7/8 issue that I couldn't find any solution for on the interwebs. The bug is as follows: if you use the Facebook JavaScript SDK to send apprequests (the invites that show up in the Facebook notifications jewel) and you're doing so through the FB.ui() method, the default settings will not work in Internet Explorer 7 and 8.

FB.ui() requests use Facebook Dialogs to render the modal. In your FB.ui() call you can reference the way in which you want Facebook Dialogs to render the modal. The options are 'page', 'popup', and 'iframe'. The Facebook documentation states that 'page' is the default, but for FB.ui({method: 'apprequests'}) calls, 'popup' is the default - which looks great in Chrome/FireFox/Safari; however, in IE, the modal never appears. So for IE users you need to set the display method to 'iframe' and it will work fine.

All you have to do is write some simple JavaScript browser detection code to toggle the display method. Here is my CoffeeScript to do this:

In case you're not a CoffeeScript fan, here is the equivalent to the above in JavaScript.

Don't get stuck in development mud

Anyone that has ever done an online startup knows that one of the hardest decisions you continually have to make is where to spend your developer time. The game is a bit of a paradox too because the more you do, the more you have to maintain. This maintenance is "developer mud", and it includes things like, coding new emails, updating old ones, testing alternative views & user flows, improving metrics visibility - the list goes on and on. All these activities are important but the big challenge is deciding when they should take priority over new features.

It's true, a new feature is unlikely to be the game changer it appears to be when it was conceived, but the same can be said for the maintenance. The big difference is how much technical debt you are building up by doing an activity. For example, building a new section of a site for users to communicate on a simple Facebook-like wall might be a great addition for users, but along with that comes the complexity of more schema, more tests, user generated content (an possibly moderation) and other ancillary needs.

One of the places we find ourselves a bit stuck in the mud at thredUP right now is with email. We send a lot of system email and a lot of marketing email. As easy as rails makes email, it is still far too painful. While solving this is not going to reduce the technical debt load, it could take the maintenance side of emails out of developer hands and give our marketers the ability to experiment and test emails freely. My next post will explore a few options out there for us with respect to transactional email.

Rails Association Tips

by Dan DeMeyere - @dandemeyere

Rails is one of those languages where you can infer how it should interpret code. A more simple way to word that is this: sometimes you'll be coding something for the hundredth time and all of a sudden you'll think to yourself 'I wonder if this will work' and you'll try to change a convention based on your previous experiences with that language. This recently happened to me and I wanted to share what I discovered.

We have a lot of named scopes in our app. Typically our named scopes look something like this:

In that example, our User model has_one :concierge_information (btw, definitely check out our new thredUP Concierge app). While I was creating this scope, I wondered if I could infer which 'joined_via' column I was referencing since I was querying over two tables. So I tried this:

And it worked! Much prettier, right? That example doesn't save a lot of keystrokes, but it should help keep things organized if you're joining across multiple tables and/or querying a lot of ambiguous columns (when you're query references a column name that exists on multiple models you're querying across). While I was writing this, I thought it might be nice to share some other association-related tips I've learned.

ActiveRecord Association Tips

Rails associations are awesome and they come with a lot of built-in class methods/helpers. The basic rule of thumb that I use is that if you're accessing an object's association, you probably have access to the ActiveRecord methods the association's model has. For example:

In that example, you can do any ActiveRecord query on that user's orders as if you were querying a subset of the Order table itself. This can be very handy if you have nested associations.

Object Association Tips

One that I recently came across was the built-in method for creating an associated record that is a has_one association. It ended up just being 'create_#{association name}'. It's not life changing, but it's nice to know. Here it is in action:

In case you're wondering what the has_many version looks like:

This brings up an important note about something I was fuzzy about until recently. When are these objects saved? Obviously a .create() call will write to the DB, but what about when you create/build the object outside of the association and then assign it afterwords? Here are some examples (these are all under the pretense that @user is already stored in the database):

That was helpful for me to learn as unnecessary .save calls result in additional calls to the database.

Lastly, I came across an edge case scenario that I was curious about. If you're using the '<<' operator to associate newly created objects, how do you know if the object you're creating failed? The answer is you don't. However, you can use the .push() method and it will do the same thing as the '<<' operator except that it will return true or false depending on whether the creation was successful or not.