Spree Commerce

Try It Now

Using Deface with Spree Commerce

Posted on May 26, 2015 by Marcin Dobrowolski

About The Author

Marcin is a developer at netguru. Before enrolling to Poznań University of Technology Marcin spent way too much time in front of a computer playing games. Finally he has figured out that the love for a shining screen can be channeled into something way more productive. Easily hyped about every new piece of technology on the market. Addicted to coffee, music in all forms, sports and computer games. Loves warmth, hates cold; the only good thing about winter in his opinion is the lack of bugs, mainly mosquitos.

Today I Learned: Deface Selectors Work on ERB Code, not HTML

Are you looking for quick solutions to your problems with code? Or want to find clever tricks you can read about in a few minutes? You’re in the right place! This is the beginning of the new post cycle: Today I Learned. In these posts, Spree Commerce Certified Partner netguru will present quick tips from its developers that they came across during their work day. The first tip comes from Marcin and concerns Deface—the gem used in the Spree ecommerce platform.

What Exactly Does Deface Do?

When working with Spree, you can use a gem called Deface which lets the developers inject code into a Spree view without overwriting the whole file. It works with HTML (ERB, Haml and Slim). In short, you select whether it should insert your piece before/after an element, replace it/remove it altogether, etc. Finding the right element to replace is easy because Deface uses Nokogiri’s implementation of CSS selectors.

The Problem with Deface

Our client asked us to replace mailto: links. Instead, we were supposed to put an email in a certain table and link them to a user’s profile. Take a quick look at this ERB code:

Unfortunately, the td had no class, so we needed a pseudo-selector to find it. Here is the selector that I thought would work:

However, for some reason the selector couldn’t find the necessary element. Here is what Deface had to say about it:

Why Didn’t it Work?

After a lot of frustration, trying different selectors, theories that Deface doesn’t find ‘a’ elements because of a bug, it turns out that Deface uses selectors on ERB files, not compiled HTML files. Moreover, you can write Deface overrides in Haml/Slim, but it will still:

  • Convert them to Erb
  • Convert Erb blocks into HTML-ish tags…
  • Do all the overrides there

So, since we want to replace an ERB block, our selector will have to contain erb[loud] instead of ‘a’.

The Final Solution

The trick that worked was to use a selector directly on the erb code:

As you can see, instead of matching an anchor element, my override matches an erb[loud] tag that is generated by Deface in an intermediate step, before printing the final HTML.

So, here’s the trick—hope you’ll find it useful! If you have any other tips and tricks for Spree, feel free to share them in comments—or link to your GitHub page.

In the next episode of Today I Learned you’ll find out how to render templates to strings in EmberJS, a tip brought to you by netguru developer Kuba. To view this post in its original format, visit the blog of netguru.