ArtBox: Sinatra Project Writeup
Tags: ruby, sinatra, bulma, flatironschool
Published: 2021-04-02 18:25:41

Today I want to talk about ArtBox, my Sinatra application project for Phase 2 of Flatiron School's software engineering program.

For my MVC CRUD application, I chose to create a website for artists to create a digital library of their art supplies to help them keep track of their collections or share them with friends. I named my website "ArtBox".

The basic models the for application are Users, Supplies, and Categories. A users has many supplies and supplies belong to a user. Supplies also belong to a category, and users have many categories through supplies. The Category model exists to add additional functionality to the application, allowing users of the site to filter down by particular categories as they browse.

I chose to utilize the Bulma CSS framework to style my site. I've been interested in learning non-bootstrap frameworks, and I found that Bulma was really quick and easy to use for the most part. I wanted to make a good-looking site, but also didn't want to sacrifice the substance of my app by spending too much time on style, and I found Bulma was a great way to do that. My html views all ended up being a little lengthy with all the extra divs and containers and whatnot, but I didn't really find that hindered my process at all.

One of the bigger challenges I ran into was figuring out how I wanted to structure the relationship between Supplies and Categories. I originally imagined Supply and Category to have a `:has_many_through` relationship, and had a Supply_Category class to facilitate that with a join table. However, as I was building out my forms, I realized that didn't make much sense to me. A supply should only have one category - it might have many tags, for instance, but if you are breaking down art supplies into categories like "colored pencils," "markers," and "watercolors," it doesn't make sense for them to belong to more than one. So, I restructured my classes and got rid of Supply_Categories.

This ended up presenting an interesting challenge for my new/edit Supply forms. I wanted users to be able to either choose from an existing category or create their own. This requires two inputs, a select dropdown and a textbox. However, having them both visible on the page at the same time would be troublesome since a supply can only have one category. I could write a validation to make sure the input would only be accepted if one or the other was used, but that just felt like bad UX to me - a user would be confused why they can't use both fields if they are present. I ended up having to search online for how to toggle visibility based on dropdown selections using Javascript/JQuery. Not one tutorial was a perfect fit for what I wanted to do, but I was able to piece together a few different techniques and came up with the following:
```html
<div class="select level-left" id="category_select">
  <select name="category[name]" id="category_name">
    <option value="" disabled selected>Select</option>
    <% @categories.each do |category| %>
    <option value="<%= category.name %>"><%=category.name%></option>
    <% end %>
    <option value="" id="new_category">--New Category--</option>
  </select>
</div>
<div class="level-right">
  <input type="text" class="input level-item"
  name="category[name]" id="new_category_name">
</div>
```
```javascript
$(document).ready(function () {
  $("#new_category_name").prop("disabled", true);
  $("#new_category_name").hide();
  $("#category_select").change(function () {
    if ($("option:checked").text() == "--New Category--") {
      $("#new_category_name").show();
      $("#new_category_name").prop("disabled", false);
      $("option:checked").prop("disabled", true);
    } else {
      $("#new_category_name").prop("disabled", true);
      $("#new_category_name").hide();
    }
  });
});
```
`#new_category_name` is the text field for writing in a new category, and we start the script off by both hiding it (so the user won't see it) *and* disabling it (which is necessary for it to not come through in params when POSTing). Then, there is an event listener which waits for a click on the dropdown menu `#category_select`. If the text of the selected option is "--New Category--", it will reveal and enable the `#new_category_name` field and disable the select box (again, so its value will not come through as a parameter). If any of the existing categories is
 chosen from the dropdown, the new category field will be hidden again, and that option will be re-enabled in the dropdown.

Making sure this app is as air-tight as possible in terms of user view/edit permissions and being able to access desired links from logical places throughout the site was a fun challenge. I had to re-record my demo video numerous times as I kept finding errors or bits of logic that didn't work quite the way I wanted them to, but in the end it was a useful process as I super comfortable with how it functions. Sinatra was a great intro-to-web-apps experience and I look forward to seeing what Rails has in store.

Github Repo: https://github.com/merlumina/artbox
Bulma CSS: https://bulma.io/