Illustrack: Sinatra Project
Tags: sinatra, flatiron, activerecord
Published: 2021-02-12 20:02:13

[Demo Video](https://drive.google.com/file/d/1jrPkc_LvThbxWZfbeVJJPHNFj8AOPm8m/view?usp=sharing)

Flatiron School's second project tasks us with making a Sinatra application that utilizes our knowledge of Active Record CRUD and ORM's. For my project, I decided to make a portfolio/e-commerce website for artists that I named Illustrack. I love to draw in my free time, so I wanted to make something that I myself would enjoy using.


After getting my basic file structure set up using the gem Corneal, the first thing I did was set up my models and associations. 

My models utilized has_many, belongs_to, and has_many_through relationships, with tag_illustration handling the many to many relationship between illustrations and tags. 

![alt text](https://dev-to-uploads.s3.amazonaws.com/i/frjnjgvjj4c2w9nkb0kc.png)
 
After setting up my Application Controller and getting just a basic index page working, the next thing I did was get the image uploading functionality up and running. I used a gem called Carrierwave which helps handle file uploading and displaying. Once that was done, I moved on to stubbing out the rest of my controller requests. 

Rather than go through all of my many, many request blocks, I'll share the most challenging one to implement. When uploading a listing, users are able to upload a new image (or images), and/or choose from images they have already uploading previously. Additionally, I didn't want images that were ONLY uploaded to a listing to appear in the overall /illustrations index. 

![alt text](https://dev-to-uploads.s3.amazonaws.com/i/e6twrpssuut4jae0ydgl.png) 

I needed a way to separate out old illustrations that were now also used in a listing, and new illustrations that were only used in a listing. I ended up adding a new boolean attribute to my Illustration model called `used_in_listing` which I used to flag illustrations that were only used in listings and should not be displayed on the portfolio side of the site. I set this in the same block where I created and assigned listing uploads:
```        
if params[:listing][:images]
            @imgs = params[:listing][:images].map do |image|
                Illustration.create(image: image, user_id: current_user.id, used_in_listing: "false")
            end

            @imgs.each do |img|
                img.used_in_listing = true 
            end

            @listing.illustrations << @imgs
        end
```

If params included images, new images would be created, and if not, the application would move on to my next code block that handled the adding of old illustrations to a listing: 
```        
if params[:listing][:image_ids]
            @old_imgs = params[:listing][:image_ids].map do |id|
                Illustration.find(id)
            end
            @listing.illustrations << @old_imgs
        end
```

The entire post request ends up looking like this: 
```
    post '/listings' do 
        if !logged_in? 
            redirect '/login'
        else

        if !valid_listing?
            flash[:message] = "Please fill out all fields."
            redirect '/listings/new'
        end

        @listing = Listing.create(title: params[:listing][:title], description: params[:listing][:description])
        @listing.user_id = current_user.id
        @formatted_price = "#{params[:listing][:price]}00".to_i
        @listing.price = @formatted_price
        @listing.save!

        
        if params[:listing][:images]
            @imgs = params[:listing][:images].map do |image|
                Illustration.create(image: image, user_id: current_user.id, used_in_listing: "false")
            end

            @imgs.each do |img|
                img.used_in_listing = true 
            end

            @listing.illustrations << @imgs
        end

        if params[:listing][:image_ids]
            @old_imgs = params[:listing][:image_ids].map do |id|
                Illustration.find(id)
            end
            @listing.illustrations << @old_imgs
        end

        @listing.save!

    end
```
It's quite long, but there were a lot of different components to handle. You'll notice at the start of my post request there are two lines for handling the price: 
```
@formatted_price = "#{params[:listing][:price]}00".to_i
        @listing.price = @formatted_price
```

The functionality is disabled on my live site, but for purchasing items off of listings I used the Stripe API. The API called for certain attributes to be formatted a specific way, which is where these two lines of code come from. In hindsight, I would have gone with a different e-commerce service as Stripe legacied many of the services that would be necessary if this was a real, usable site (such as attaching shipping costs to items, etc). However, it was a HUGE learning experience integrating the API, and definitely the most difficult and time consuming part of building this application. Even though that functionality is not live, it was in no way a waste of time as I learned a *ton* by going through the practice of integrating. 

Overall, the experience of building this application was a huge learning experience and a ton of fun. It's such an awesome feeling to be able to see and use something that you built from scratch. Looking forward to our next phase!