Sort Shopify Liquid Collection By A Nested Property

Suppose you want to sort or filter a Shopify collection by a sub/nested property. Well, this is an example of how you’d sort a Shopify collection by a nested property, specifically how to sort by a setting property of a logo list block.

Shopify tab example
Shopify filter tab example

I created a Shopify tab snippet to filter and sort the above list of logo blocks by a property within a single logo/block. The code below gets all the blocks in the logo list section, maps over the settings and returns the items where the logo_list property equals “brewery” then sorts the results by title. If you don’t need to return a specific sub-set of data and only want to sort by the property then simply remove | where: “logo_category”, “brewery” from the assign block.

{% assign breweries = section.blocks | map: 'settings' | where: "logo_category", "brewery" | sort: "title" %}

{% for block in breweries %}
    {%- assign logo = block.logo -%}
    {%- assign url = block.url -%}
        <div class="module-inline-item dynamic-logo-list-item" {{ block.shopify_attributes }}>
            {% if url != blank %}
              <a href="{{ url }}" target="_blank">
            {% endif %}

            {% if block.logo != blank %}
              {%
                include 'rimg',
                img: logo,
                size: '330x280',
                lazy: true
              %}
            {% else %}
              {{ 'logo' | placeholder_svg_tag: 'placeholder-svg' }}
            {% endif %}

            {% if url != blank %}
                </a>
            {% endif %}
          </div>
      {% endfor %}

And that’s all you need to do to filter a Shopify collection by a nested property. I will post the code for the full tab snippet in another post.

How To Create A Reusable Select List In React

This tutorial is on how to create a reusable dropdown list component in React. I broke the functionality down into two components — the actual select dropdown list component and the calling parent/calling component.

The parent component will be App.js and a component called DynamicSelect.js will handle the select list functionality. The entire source code project is on GitHub.

Let’s start with the DynamicSelect component. The DynamicSelect component is the component which will render an array of Seinfeld characters into select list and pass back the selected value via the props object to the parent component. When the onChange event is fired for the select list the event is passed into the handleChange function. This function will pass the selected value back to the parent (App.js) via the props object.

DynamicSelect.js Component

import React, {Component} from 'react';

class DynamicSelect extends Component{
    constructor(props){
        super(props)
    }

    //On the change event for the select box pass the selected value back to the parent
    handleChange = (event) =>
    {
        let selectedValue = event.target.value;
        this.props.onSelectChange(selectedValue);
    }

    render(){
        let arrayOfData = this.props.arrayOfData;
        let options = arrayOfData.map((data) =>
                <option 
                    key={data.id}
                    value={data.id}
                >
                    {data.name}
                </option>
            );

            return (
            <select name="customSearch" className="custom-search-select" onChange={this.handleChange}>
                <option>Select Item</option>
                {options}
           </select>
        )
    }
}

export default DynamicSelect;

App.js Component

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import DynamicSelect from './DynamicSelect';

const arrayOfData = [
  {
    id: '1 - Jerry',
    name: 'Jerry'    
  },
  {
    id: '2 - Elaine',
    name: 'Elaine'    
  },
  {
    id: '3 - Kramer',
    name: 'Kramer'    
  },
  {
    id: '4 - George',
    name: 'George'    
  },
];

class App extends Component {
  constructor(props){
    super(props)
    this.state={
      selectedValue: 'Nothing selected'
    }
  }

  handleSelectChange = (selectedValue) =>{
    this.setState({
      selectedValue: selectedValue
    });
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Dynamic Select Dropdown List</h1>
        </header>
        <p className="App-intro">
          <DynamicSelect arrayOfData={arrayOfData} onSelectChange={this.handleSelectChange} /> <br /><br />
          <div>
            Selected value: {this.state.selectedValue}
          </div>
        </p>
      </div>
    );
  }
}

export default App;

And that’s it. The repository for this code is available on GitHub in this class fashion. This functionatliy can be easily replicated via functional components with hooks as well.

Why I Write Unit Tests

In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use — wikipedia

Unit tests, who needs em? We all do. There are a lot of resources online that will tell you why unit testing is important or why writing unit tests before building implementations is a good idea. But I’m here to tell you how unit tests can save you a massive production headache.

A while back, a coworker pushed code to production that consumed and parsed large .csv files uploaded by users. The code looped through the file then parsed and mapped each record to the associated record in the model. The model contained a few bool fields that were populated by executing the C# Boolean.TryParse method against the text field to convert the string from the file to bool. If the TryParse method returned false then the value in the csv file must have been falsy, and vice versa for true. The record was applied to the model and saved to the database.

As it turned out, our code didn’t work as expected which caused a major problem. For bool fields users would upload either a 1 or 0. 1 being true and 0 being false. Because the source was a csv file all values were imported as strings. Therefore, before applying the values to our model, we must convert the string representation to the appropriate type within the model.

Here’s an example of the code, the Parse method below takes a string argument named parsable, does a Boolean.TryParse against parsable and returns the newly converted value.

	
	public static Main(){
	    var trueFalse = Parse("1");
	}
	
	public bool Parse(string parsable)
	{
		 bool flag;
		 bool result = Boolean.TryParse(parsable, out flag);
         return flag;
	}

From looking at the method and without knowing how C# Boolean.TryParse converts the string argument “1” to bool you’d think that this method returns true, not false. But in reality the above method returns false. Even though 1 generally equals true in most contexts, if passed in as a string the result is false, not true.

If we would have had proper unit tests set up we would have written a unit test that looks something like this:

[TestMethod]
public void Parse_BooleanTryParseString__ReturnsFalse()
{
    string stringToParse = "1";
    bool expected = true;
    bool actual = Parse(stringToParse);

    Assert.AreEqual(expected, actual);
}

The above unit test would have failed and we’d have found the problem, fixed it and been on our way. Unfortunately for us, we didn’t have a unit test for the above Parse method and QA didn’t catch the issue during their testing. The code eventually made its way to production, users start uploading files against the new code and yadda, yadda, yadda…we end up with a lot false values that should be true.

I've made a huge mistake

The good news is we were able to recover the lost data. But the recovery process took a few days and a lot of manual work which set us back on our timeline, not to mention created a garbage truck full of unwanted stress while we scrambled to recover the data and explain to our stakeholders that we’d made a huge mistake.

The takeaway my team and I had from this experience is how valuable a unit test can be. Unit tests are not just a key part of the testing process, but they’ve proven to be invaluable in making sure the code you write is actually doing what you think it’s doing.