Building an Event Landing Page Management System
Tags: ruby, webdev
Published: 2021-12-20 00:07:15

Frontend: [joedietrich-dev/event-page-client](https://github.com/joedietrich-dev/event-page-client)
Backend: [joedietrich-dev/event-pages-server](https://github.com/joedietrich-dev/event-pages-server)

## Inspiration

I was inspired to build this when I was tasked with repeatedly hand-coding landing pages in simple html. This was inefficient in terms of time spent and meant I was the only person around able to maintain the pages or make any changes. I set out to create a proof-of-concept / MVP event page builder. It has nearly all the entities I need to build those hand-coded pages.

## Basic Features
This is the backend for a simple proof-of-concept event page creator. It is designed to let you build events with:

- Hosts
- Honorees
- Panels & Panelists
- Sponsors of different levels

## What I Used

### Frontend
- [React](https://reactjs.org/) / [Create React App](https://create-react-app.dev/)
- [React Router v6](https://reactrouter.com/) - For client-side routing
- [MUI](https://mui.com/) - A UI component library
- [MUI Icons](https://mui.com/components/material-icons/) - For iconography

### Backend
- [Sinatra](http://sinatrarb.com/) - a domain-specific language used to build the API framework for the app
- [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) - Rails' ORM, here used with Sinatra to map the Ruby classes to the database
- [SQLite](https://www.sqlite.org/index.html) - the database engine used in this project
- [Rake](https://github.com/ruby/rake) - to run commands on the command line
- [Faker](https://github.com/faker-ruby/faker) - used to build out seed data

## Entities and their relationships
Before I built out the migrations for the database, I sat down and planned the data structure. Below is a diagram of the different tables in the application's database and their relationships to one another.

![Event Page Management Entity relationships](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xk0m1epkda7xbrl6fde4.png)

## Faker
Before I started building out the front end of the application, I knew I needed data to work with. Having real-looking data helps in the design process, and using [Faker](https://github.com/faker-ruby/faker) means you don't need to build out your database by hand.  
Faker has a large number of different generators you can use to make your data more realistic or even if you just want to get a little more creative. I used and would recommend the:
- Company generator - for company names
- Lorem generator - for lorem ipsum placeholder text
- Number generator - for years
- Nation and Hobby generators - for somewhat sensical sounding event names (e.g. 2022 Malaysian Drumming Awards)
- Hipster and GreekPhilosopher generators - for English (or English-adjacent) text placeholders
- Name and Job generators - for people's names and job titles

All of these together helped me create reasonable placeholder data, which you can see in the [demo video](https://www.youtube.com/watch?v=Mzy1-Xqw9qE).

## Eliminating Orphan Records
When I started building the interface for the app, I realized that deleting certain entities, like events or panels, could leave orphaned records. These were records that could not logically exist independently of their parent entities - especially the linking records between the panels and panelists and events and sponsors. I didn't want this, since orphaned records are just taking up space, at best, and could cause unexpected behavior at worst.

I solved this problem by setting the [`dependent: :destroy`](https://guides.rubyonrails.org/association_basics.html#dependent) option on some of my models' associations.

```ruby
class Panel < ActiveRecord::Base
  belongs_to :event
  has_many :panel_panelists, dependent: :destroy
  has_many :panelists, through: :panel_panelists
  has_many :panel_sponsors, dependent: :destroy
  has_many :sponsors, through: :panel_sponsors
end
```

Take the `Panel` class as an example. A panel belongs to an event, and has many panelists and sponsors through linking models. When a panel is deleted, the panelists and sponsors should remain, since they can be associated with many panels. The linking records, `panel_panelists` and `panel_sponsors` are unique to the panel being deleted. With `dependent: :destroy`, those records are deleted along with the panel.

## End
Thanks for reading! For a walkthrough, take a look at the [demo video](https://www.youtube.com/watch?v=Mzy1-Xqw9qE).