Are you looking for quick solutions to your problems with code? You'll like our new post cycle: Today I Learned. We’re going to present quick tips which our developers during their everyday work. The first tip comes from Marcin and concerns Deface - the gem used in Spree e-commerce platform. Enjoy!
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, we’re going to present quick tips from our developers which they came across during their working day. The first tip comes from Marcin and concerns Deface - the gem used in Spree e-commerce platform.
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.
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:
<td> had no class, so we needed a pseudo-selector to find it. Here is the selector that I thought would work.
tr[data-hook=admin_orders_index_rows] td:nth-of-type(6) a
However, for some reason the selector couldn’t find the necessary element. Here is what Deface had to say about it:
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...
<% some_method %> converts to
<erb silent> some_method </erb>
<%= some_method %> converts to
<erb loud> some_method </erb>
So, since we want to replace an ERB block, our selector will have to contain
erb[loud] instead of
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 our developer Kuba. Hope you’ll get back to our blog soon!