Archive:

Make-My-Movie-List App


This app was inspired by the website MyAnimeList.net. This website aims to be a a place where people can rate movies, and curate their own list of favorite movies.

Frontend

The divs were first developed in Figma before implementing the assets in my code. The planning for this website was done much more efficiently than my other projects. Over the course of this bootcamp I learned how to develop programs in way that will help me avoid future obstacles. I thought about the functionality I want to provide my users and how it would be best to implement them through components. Knowing that I will be needing to do all my coding in a Home component instead of the default App component made implementing user authentication much easier than before. I started developing the project in the Home component and only after I figured out all the functionality for it I added user authentication towards the end.

 <div className="App">
       { user ? (
        <Routes>
         <Route path='/' element={<Home
         handleLogout={handleLogout}
         setUser={setUser}
         changeUserpic={changeUserpic}
         user= {user}
         id = {user.id}/>}/>
          <Route path='/movies'element={<Nav />}>
            <Route path=':id' element={<ReviewPage  handleAddRev={handleAddRev}  movlist={movlist} setMovlist={setMovlist} />}/>
          </Route>
        <Route  path="/signup" element={<SignUp user={user} setUser={setUser} handleLogout={handleLogout} />} />
        <Route  path="/login" element={<Login setUser={setUser} user={user} />} />
        </Routes> ) : (
        <Routes>
        <Route  path="/login" element={<Login setUser={setUser} user={user} />} />
        <Route  path="/signup" element={<SignUp user={user} setUser={setUser} handleLogout={handleLogout} />} />
        </Routes>
     )}
    </div>);
    }
 export default App;

As you can see in the return, it checks to see if “user” exists before navigating to either the sign-up page or the home page of the app.

Backend

The backend for this app was set up very similar to the last one I did except this time I added interaction with Active Storage. Active Storage is an in house method for Rails to facilitate uploading files to cloud storage services like Amazon S3, Google Cloud Storage, and Microsoft Azure Storage. For this program I used Google Cloud Storage, because it was free and had a lot documentation to help me throught the steps.

After downloading Active Record it loads a migration file to creat the following ActiveStorage Tables:

 enable_extension "plpgsql"

  create_table "active_storage_attachments", force: :cascade do |t|
    t.string "name", null: false
    t.string "record_type", null: false
    t.bigint "record_id", null: false
    t.bigint "blob_id", null: false
    t.datetime "created_at", null: false
    t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
    t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
  end

  create_table "active_storage_blobs", force: :cascade do |t|
    t.string "key", null: false
    t.string "filename", null: false
    t.string "content_type"
    t.text "metadata"
    t.string "service_name", null: false
    t.bigint "byte_size", null: false
    t.string "checksum", null: false
    t.datetime "created_at", null: false
    t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
  end

  create_table "active_storage_variant_records", force: :cascade do |t|
    t.bigint "blob_id", null: false
    t.string "variation_digest", null: false
    t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
  end

Active Storage now allows me to use the following macro to sync the attribute ‘avatar’ to the User class.

class User < ApplicationRecord
    has_secure_password
    has_many :reviews
    has_one_attached :avatar


    def public_url
        "https://storage.googleapis.com/movie_bucket_list/#{self.avatar.key}"
    end
end

I had to create a custom method to navigate to the correct file name on Google Cloud, as it was changing the name to string value of the key.

The way the frontend handles this request looks like this:

const handleSubmit = (event) => {
  event.preventDefault();

  const formData = new FormData();
  formData.append("avatar", userpic);
  fetch(`/users/${id}`, {
    method: "PATCH",
    body: formData,
  })
    .then((r) => r.json())
    .then(
      fetch("/me").then((r) => {
        if (r.ok) {
          r.json().then((user) => setUser(user));
        }
      })
    );
  ref.current.value = "";
  forceUpdate();
};

I had to send the file through FormData in the body of the request for the backend to then handle it. Google Cloud allows free storage for up to 5 gb which is a big part of why I opted for it over the other services.

Overall I had a great time making this website. It was an example of everything I’ve learned during my at the time at bootcamp while also testing my ability to adapt new technologies into my assignments. I really enjoyed teh overall process and seeing how far I’ve come since the day one. For more information please click on the image below for a direct link to the GitHub page.



movies