[null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/slaveryfootprint_small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/slaveryfootprint_small.png", "formatted_filename": "slaveryfootprint small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/jamesanderson613_small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/jamesanderson613_small.png", "formatted_filename": "jamesanderson small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/diy_small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/diy_small.png", "formatted_filename": "diy small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/dangersoffracking_small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/blog/dangersoffracking_small.png", "formatted_filename": "dangersoffracking small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://tup.s3.amazonaws.com/cms/labs/images/toggle-selectors.png", "src": "https://tup.s3.amazonaws.com/cms/labs/images/toggle-selectors.png", "formatted_filename": "toggle selectors"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/stella-small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/stella-small.png", "formatted_filename": "stella small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/1minus1-small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/1minus1-small.png", "formatted_filename": "minus small"}, null, {"document_url": "http://labs.thredup.com/?page=2", "unformatted_src": "https://s3.amazonaws.com/dandemeyere_production/2012/fork-small.png", "src": "https://s3.amazonaws.com/dandemeyere_production/2012/fork-small.png", "formatted_filename": "fork small"}, null, null, null, null]
by Dan DeMeyere -Â @dandemeyere

Google PageRank

SEO Elevators

SEO Detractors

SEO Summary


Active Record

Gem Bumps
 

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.

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.


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.


JavaScript Debugging Console DOM Tips


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.


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. 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. 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.


Storing your ActiveRecord Objects in Redis

Link to article â

Converting Dates Between Ruby and JavaScript


Lazy Evaluation and Method Chaining


ActiveRecord Key Value Stores



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.

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.


ActiveRecord Association Tips

Object Association Tips

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

thredUP Engineering

Browse the Archive »