<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jessica Vaughn</title>
    <description>The latest articles on Forem by Jessica Vaughn (@jvaughn619).</description>
    <link>https://forem.com/jvaughn619</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1004912%2F9de96c62-5e65-4838-adcc-e7b1d5fc5bc8.jpeg</url>
      <title>Forem: Jessica Vaughn</title>
      <link>https://forem.com/jvaughn619</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jvaughn619"/>
    <language>en</language>
    <item>
      <title>Education to Engineering - my Flatiron School experience</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Wed, 05 Jul 2023 23:05:28 +0000</pubDate>
      <link>https://forem.com/jvaughn619/education-to-engineering-my-flatiron-school-experience-2hdc</link>
      <guid>https://forem.com/jvaughn619/education-to-engineering-my-flatiron-school-experience-2hdc</guid>
      <description>&lt;p&gt;I started the year 2023 with a pretty big goal - to change careers from public education to software engineering. As anyone who has made a big life decision knows, there are a lot of emotions that go along with change. In January, I enrolled in and began the Flatiron School software engineering bootcamp as a flex student, and six months later I am writing my final blog post and getting ready to enter the job market. This post is intended to answer the question I've been asked many times since making the decision to switch careers - "What has your experience at Flatiron School been like?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Backstory
&lt;/h2&gt;

&lt;p&gt;No experience can be separated entirely from its context - so as I share my thoughts here, I also want to share a little of my personal context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(TLDR at end of section)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I love teaching and being a teacher. I taught high school band for eight years, the first five in person at a Title I school (my old high school, at that!), the sixth online during COVID, and the final two in a different school that is rated as one of the best in the state. I am incredibly grateful for the impact I was able to have on students and for the person I became because of the students and adults I met along the way. I never imagined myself doing anything other than teach - I planned to be a band director on a marching band field or staying late at school for an event until retirement age - and then COVID happened.&lt;/p&gt;

&lt;p&gt;Sitting still isn't a skill I had developed much of in my life - I was always at some band event or finding the next thing to say 'yes' to. Most of the time I would leave for work around 6:00am and not return home until somewhere between 7:00pm and 9:00pm. My Saturdays were busy with marching band and other music events, and I really loved it. When Spring Break of 2020 arrived, an announcement came over the school intercom that the break had been extended for an extra week due to the Covid-19 outbreak. I hugged students goodbye and said I'd see them in a couple of weeks. And then the world stopped. Eventually we were told we would not come back to school in person for the end of the year, and because we couldn't ensure students all had access to technology, our district developed writing assignments for each class that students had to complete to get their course credit. I set up some Google meets where my band students could come and see each others' faces. We talked about plans for the following year and how excited we were to be able to make music together and be in person again in just a few months.&lt;/p&gt;

&lt;p&gt;After a summer of debating across the nation whether schools could be in person or not, our district decided it was safest to stay fully remote for the 20/21 school year. We tried our hardest to keep everything operating as usual for our students. 0/10 would recommend trying to do band online, but we tried our best! Many of our classes ended up being discussions of what music meant to us, how we were doing, etc. My school opted for a unique schedule where students took two 3-hour long classes - one from 7:30-10:30am and the other from 12:30-3:30pm, all online, for a month. After a month, they switched to their next two classes on the same schedule. As a teacher, I taught during one block and lesson planned during the other block - turns out it takes awhile to plan for a 3-hour long lesson each day. Over time, I figured out a planning routine that took about 2 hours, so I'd teach from 7:30-10:30am, plan until 12:30pm, then have the rest of the day to fill. I couldn't see my students and couldn't leave my house, like the rest of us. Eventually, I found a routine I really enjoyed that allowed me to exercise, plan meals, read a book, or have some other time for myself in the day to fill my extra afternoon time.&lt;/p&gt;

&lt;p&gt;My husband, who was teaching orchestra alongside me at the same school, decided during the pandemic he did not want to teach anymore and enrolled in Flatiron School at the end of the 20/21 school year. At the same time, I decided it was time to move to a different school and was offered a job at a prestigious school in the state. I taught at this new school for two years - we were back in person and I got to build relationships with students again and make music, but now imagining myself as a band director until retirement was daunting instead of exciting. I'm still not entirely sure what changed, but I knew staying in education was not filling my cup anymore and I needed to change things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; I loved teaching at one point, the pandemic somehow changed all the things, post-pandemic teaching was no longer fulfilling and I decided to change careers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting a Program
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I can teach myself to code. I know how I learn, I have a master's degree in education, for goodness sake. I should be able to learn online with free resources. My husband is a software engineer, I can just ask him questions!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These were all thoughts I had while trying to remember HTML from my MySpace days, reading through Odin Project resources, and generally banging my head into my desk while trying to self-teach myself to code. I had zero experience with coding (aside from that sweet mySpace profile where music would start playing when you landed on my profile) and felt generally overwhelmed by concepts. I remember going through an HTML/CSS lab on the Odin Project site while waiting for a plane to fly home in July of 2022 - so I spent about five months trying to teach myself to code.&lt;/p&gt;

&lt;p&gt;I realized I needed a program with structure and resources I could lean into when I got stuck - the Flatiron School was a pretty easy choice for me as both my husband and a close friend had gone through the program and gotten jobs as software engineers. Both went through the Ruby and Ruby on Rails curriculum and were incredibly jealous I would get to learn Python and Flask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flex Program &amp;amp; Time Management
&lt;/h2&gt;

&lt;p&gt;I decided to enroll in the Flex program so I could finish out my year of teaching while enrolled. Since I was starting the program in January of 2023, I hoped I would wrap the program up by the start of summer, start a job search, and ideally be employed by the fall when my paychecks would run out.&lt;/p&gt;

&lt;p&gt;The Flatiron School program is organized into five phases by language or framework. My curriculum included:&lt;br&gt;
Phase 1 - JavaScript&lt;br&gt;
Phase 2 - React&lt;br&gt;
Phase 3 - Python&lt;br&gt;
Phase 4 - Flask&lt;br&gt;
Phase 5 - Capstone Project&lt;/p&gt;

&lt;p&gt;You are expected to complete pre-work and come into the program with an understanding of HTML and CSS, since Flatiron doesn't explicitly teach these languages.&lt;/p&gt;

&lt;p&gt;I taught a normal schedule each day and then would spend a few hours each night coding. The teaching position I took at my new school was an assistant band director position, so many of the responsibilities I had at my first job were no longer in play. The spring is also less busy for bands, so I was able to mostly focus on teaching my classes in the day and come home and code unless I had an extracurricular event. &lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Curve
&lt;/h2&gt;

&lt;p&gt;One of the most important skills you learn through coding is how to research information. I would argue the second-most important skill is learning when to ask someone else for help. Again, former teacher here, I thought I could figure out everything on my own with enough research, but as an engineer it is very different. &lt;/p&gt;

&lt;p&gt;There was a huge learning curve for me in determining the best resources to utilize and in learning where to find help when I needed it. I had read in the pre-work and phase 1 curriculum that I should spend about 45 minutes on a lab max before seeking help from a technical coach or instructor. Even knowing this recommendation, I found myself spending hours on the same lab, feeling frustrated when I couldn't figure out how to solve it. &lt;/p&gt;

&lt;p&gt;It took me about half of phase 1 before I was willing to reach out to a technical coach when I was stuck. When I finally connected with the TC, I remember them saying 'Oh yeah, I got stuck on this when I was a student in the program too...' They were able to help me through part of my challenge, but they also got stuck on one of the more challenging parts of the lab. At the time, I felt really frustrated that the coach could not help me through the problem. I reluctantly reached out to my husband, who went back into his own GitHub forked copy of the lab, checked his solution, and said 'Oh shoot, I guess I never figured out that part either. Well, I got a job so I think you'll be fine, you should move on.' &lt;strong&gt;This answer was so frustrating.&lt;/strong&gt; &lt;em&gt;How am I supposed to just move on when I don't understand? I need to understand everything or I'll be lost!&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;After pushing through the phase 1 JavaScript curriculum, I designed my first project and reached my first assessment. I was really proud of my project - I built a clone of Tinder for dogs and even got my data to persist from my JSON file. I was so nervous for my assessment. In the Flatiron program, each phase assessment with an instructor has three parts - a conceptual verbal exam, a project showcase, and a live coding challenge. I made it through the first two parts fine, but when getting to the code challenge I froze up. I remember feeling overwhelmed and frozen - I didn't know how to figure out the answer and so I couldn't do anything. I failed the live coding portion and had to schedule a retake. I felt so disappointed in myself. &lt;em&gt;Maybe I shouldn't leave teaching, I'm good at my job and even though I'm not happy, I can stay and just push through it. I'm not smart enough to be a developer. I can't do this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's where context is important - not only did I fail at my first assessment attempt, all of my family and some of the few teacher friends I had told about my career change reminded me if I could always go back to teaching if my new career plan didn't work out. On top of feeling disappointed in myself, I also felt guilt for leaving education and my students, anxiety around not finishing the program quickly enough to keep our family income afloat, plus whatever mixed emotions came from hearing that at least I had a back-up plan that made me unhappy I could return to if I couldn't cut it. I imagine all of these factors combined made my failing the assessment that much worse. In perspective looking back, failing the assessment was a tiny misstep in an overall much larger journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Surges and Slips
&lt;/h2&gt;

&lt;p&gt;Throughout phases 1 through 3 of the Flatiron School program, I would describe the experience in terms of surges and slips. There were times I felt I was really understanding the curriculum (surges) and times I had to look at the solution branch for every lab and felt there was no way I could understand the content (slips). Once I told my students in mid-February I would not be returning next year, the career change started to feel real and I pushed myself to put even more time into the curriculum. By resigning my position, I eliminated one of the 'back-up plans'. Again, lots of emotions but I continued on, passed my second attempt at the phase 1 assessment, and continued through the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Curriculum &amp;amp; Career Preparation
&lt;/h2&gt;

&lt;p&gt;Flatiron School has recently reconfigured the program to correlate career preparation with phases of curricular instruction. At the end of phase 2, you must have your LinkedIn profile set up and at the end of phase 4, you submit a draft of your resume. Students receive feedback on both assignments from a career coach. The feedback I received was timely and detailed. I am really grateful to have started this preparation early, as it encouraged me to design a &lt;a href="https://jessicavaughn.netlify.app/"&gt;portfolio website&lt;/a&gt; and to start thinking about networking early on in the program. As I enter the job market, I have a polished &lt;a href="https://docs.google.com/document/d/1HzjC4m3uOv3IWioJ8PKQpEgsCn6DVPieM0wAEXfgl4o/edit"&gt;resume&lt;/a&gt; and an active &lt;a href="https://www.linkedin.com/in/jessicavaughn619/"&gt;LinkedIn&lt;/a&gt; profile to leverage.&lt;/p&gt;

&lt;p&gt;After completing my phase 3 Command Line Interface project, I really felt like the knowledge I had learned throughout the program settled in and phase 4 and 5 were really fun. I got to design my first two full-stack web applications, &lt;a href="https://youtu.be/DFA_5AwnnIw"&gt;myTunes&lt;/a&gt; (a Spotify clone) and &lt;a href="https://youtu.be/jWwT2GTx5rs"&gt;Craftsy&lt;/a&gt; (an e-commerce application). In my final project, I was especially excited to research and implement Google authentication and PayPal checkout. I could not have imagined being able to build such a comprehensive application back when I started this program a mere six months ago. I am so proud of how far I have come through this program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Program Support
&lt;/h2&gt;

&lt;p&gt;The flex program at Flatiron School worked well for me as an independent learner. In the first two phases, I really struggled with availability of support - most of the time I was coding on MST in the evenings or on the weekends, when instructor support for the EST-based program was not available. If I felt I needed help from an instructor, the soonest I could book a time was about four days out. Most of the time, I booked a 1 on 1 with an instructor and then ended up cancelling it after figuring out the problem myself since the next appointment was so far away. At first this was really frustrating, but eventually I learned to just review the solution branch if I was stuck and to go ahead and move ahead. I felt I learned the most during the project portion of each phase when I had to design a project that solved a real-world problem and use my new knowledge to create a functional product.&lt;/p&gt;

&lt;p&gt;The biggest support for me during the program was the Community Stand Up channel, first on Slack, then on Discord after the school migrated. Every day I posted what I had worked on the day before, my goal for the day, and any blockers I was facing that day. I really appreciated the accountability the channel gave me and ended up connecting with other students through the daily ritual.&lt;/p&gt;

&lt;p&gt;When I was able to connect with an instructor (typically for project support), the direction I received was awesome and I felt very supported. Each of my instructors cheered me on and I know they wanted to see me succeed. When starting the program, I expected more of a hand-holding approach, but in retrospect am glad I had to figure things out for myself much of time. I now feel well-equipped to take on a career in this field where I will likely spend at least as much time researching and asking others for help as I do actually coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps &amp;amp; Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I completed my capstone project this week and as I wrap up this blog post, I've completed the final requirement for the Flatiron School software engineering program. Next up - I begin 180 days of career support!&lt;/p&gt;

&lt;p&gt;I hope this post, in addition to being pretty cathartic for myself, lets anyone on a journey of change into my inner world and thoughts and maybe encourages you to think about your own. It's tough to share the negative feelings we have and I think many of us associate those negative feelings with our sense of self-worth. Whatever journey you are on, I hope that you can separate your emotions from your value and remember that who you are is enough. Best wishes to you!&lt;/p&gt;

</description>
      <category>flatiron</category>
      <category>coding</category>
      <category>career</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Google OIDC with Flask-React</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Wed, 05 Jul 2023 20:45:36 +0000</pubDate>
      <link>https://forem.com/jvaughn619/google-oidc-with-flask-react-4h40</link>
      <guid>https://forem.com/jvaughn619/google-oidc-with-flask-react-4h40</guid>
      <description>&lt;p&gt;When determining how to authenticate users for an application, keeping a user's data secure is the most important consideration. While there are libraries for hashing and salting passwords to avoid storing them in a local database (which should NEVER be done!), utilizing OIDC to log users into a third-party application is a safe way to handle user authentication. Additionally, users may prefer signing in through credentials they already have, such as Google or a social login, and do not have to remember yet another set of login credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OIDC?
&lt;/h2&gt;

&lt;p&gt;OIDC stands for OpenID Connect - it allows for third-party applications to authenticate and verify the identity of users and allows the third-party application to access profile information for the user. It is an additional security layer built onto the OAuth 2 framework. OIDC allows the applications to request information on behalf of the user after verifying the user already has an account with the provider. OIDC is compatible with various social networks - we will look at implementation with Google in this blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of OIDC Process
&lt;/h2&gt;

&lt;p&gt;Excerpted from &lt;a href="https://realpython.com/flask-google-login/"&gt;Real Python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Third-party application (client) registers for client credentials from a provider (like Google); client specifies what information they would like to have access to from users&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; The client sends a request to the provider’s authorization URL&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; The provider asks the user to authenticate their identify by logging in with their provider credentials&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; If the user is authenticated, the provider asks the user to consent to the client acting on their behalf and accessing information specified in step 1&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; If the user provides consent, the provider sends the client a unique authorization code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; The client sends the authorization code back to the provider’s token URL&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; The provider sends the client tokens to use with other provider URLs on behalf of the user&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;This blog assumes a Flask-React application is already created along with a database - I typically organize my project tree with a 'client' folder housing the React application and a 'server' folder housing the Flask application. Feel free to clone and fork my &lt;a href="https://github.com/jessicavaughn619/phase-5-craftsy/tree/main"&gt;repo for Craftsy&lt;/a&gt;, an e-commerce application that utilizes Google login with OIDC.&lt;/p&gt;

&lt;p&gt;Create a requirements.txt file at the root of your project directory and add the following requirements:&lt;br&gt;
&lt;code&gt;requirements.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requests==2.21.0
Flask==1.0.2
oauthlib==3.0.1
pyOpenSSL==19.0.0
Flask-Login==0.4.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install these requirements, enter the pipenv shell and run pip install -r requirements.txt&lt;/p&gt;

&lt;p&gt;You'll install additional packages throughout the project. &lt;/p&gt;

&lt;p&gt;Create a .env file at the root of your project directory. Remember to add this file to your gitignore to avoid pushing up secrets to your GitHub repository. OIDC with Google login requires your Flask application be configured with a SECRET_KEY, GOOGLE_CLIENT_ID, and GOOGLE_CLIENT_SECRET, which should all be stored as variables in your .env file to avoid sharing secrets. Register your third-party application on the &lt;a href="https://console.cloud.google.com/"&gt;Google Cloud Console&lt;/a&gt;, then add your Client ID and Client Secret from the Cloud Console to your .env file. The Secret Key can be any random key you would like.&lt;/p&gt;

&lt;p&gt;Additionally, I have my React application configured to run on port 4000 and my Flask application configured to port 5555. You'll see these ports referenced throughout this blog, make sure to change them to your own ports if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;server&lt;/code&gt; folder&lt;br&gt;
I organize my server-side code within the &lt;code&gt;server&lt;/code&gt; folder into four Python files: &lt;code&gt;app.py&lt;/code&gt; &lt;code&gt;config.py&lt;/code&gt; &lt;code&gt;models.py&lt;/code&gt; and &lt;code&gt;seed.py&lt;/code&gt;&lt;br&gt;
As you add imports, make sure to also install them from your pipenv shell using pip install.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;config.py&lt;/code&gt;&lt;br&gt;
Top level imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from dotenv import load_dotenv
from flask import Flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantiate your Flask app in this file. The required code for utilizing Google and OIDC is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;load_dotenv()
app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY')
app.config['GOOGLE_CLIENT_ID'] = os.environ.get("GOOGLE_CLIENT_ID", None)
app.config['GOOGLE_CLIENT_SECRET'] = os.environ.get("GOOGLE_CLIENT_SECRET", None)
app.config['GOOGLE_DISCOVERY_URL'] = (
    "https://accounts.google.com/.well-known/openid-configuration"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://pypi.org/project/python-dotenv/"&gt;dotenv&lt;/a&gt; and &lt;a href="https://docs.python.org/3/library/os.html"&gt;os&lt;/a&gt; are Python modules that allow you to access the variables from your .env file. Remember to instantiate with load_dotenv() at the top of your config file or your .env variables will not be loaded into your application correctly.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt;&lt;br&gt;
Top level imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from flask import (
    redirect, 
    request, 
    session, 
    make_response, 
    jsonify,
)
from flask_login import (
    LoginManager,
    current_user,
    login_user,
    logout_user,
)
from flask_restful import Resource
from oauthlib.oauth2 import WebApplicationClient
from config import app
from models import User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;login_manager = LoginManager()
login_manager.init_app(app)

GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = (
    "https://accounts.google.com/.well-known/openid-configuration"
)
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

client = WebApplicationClient(GOOGLE_CLIENT_ID)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code block above, we are instantiating the LoginManager from flask_login, pulling in our Google environment variables from our .env, and instantiating our WebApplicationClient with our Client ID from the Google Cloud Console.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;models.py&lt;/code&gt;&lt;br&gt;
Top level import required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask_login import UserMixin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a User model with the minimum following columns and method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class User(db.Model, UserMixin):
__tablename__ = 'users'

id = db.Column(db.String, primary_key=True, unique=True)
name = db.Column(db.String)
email = db.Column(db.String)
profile_pic = db.Column(db.String)

def get(user_id):
    user = User.query.filter_by(id=user_id).first()
    return user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UserMixin import adds the methods necessary for OIDC login without having to write them out yourself. Check out the &lt;a href="https://flask-login.readthedocs.io/en/latest/_modules/flask_login/mixins/"&gt;documentation here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The four columns specified in the User model connect to the information we'll request from Google and receive back. It is essential that the id is set to a String data type because the Google id being sent to us is a String.&lt;/p&gt;

&lt;p&gt;Run a database migration to add your User model. Let's return to our &lt;code&gt;app.py&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

def get_google_provider_cfg():
    return requests.get(GOOGLE_DISCOVERY_URL).json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the @login_manager to load our user from the User.get() method which wrote in our &lt;code&gt;models.py&lt;/code&gt; file. The get_google_provider_cgf() method is required to configure our Flask app.&lt;/p&gt;

&lt;p&gt;We need to write four endpoint routes into our &lt;code&gt;app.py&lt;/code&gt; file to handle all of the steps of OIDC authentication: Home ('/'), Login ('/login'), Login Callback ('/login/callback'), and Logout ('/logout'). I mixed in Flask Restful conventions for my Home (CheckSession) and Logout routes as I later added local sign up and login. I have extracted this code to include only the parts that are required for Google login with OIDC.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CheckSession(Resource):
    def get(self):
        if current_user.is_authenticated:
            return current_user.to_dict(), 200
        return {'error': '401 Unauthorized'}, 401

@app.route("/login")
def login():
    google_provider_cfg = get_google_provider_cfg()
    authorization_endpoint = google_provider_cfg["authorization_endpoint"]

    request_uri = client.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=request.base_url + "/callback",
        scope=["openid", "email", "profile"],
    )
    return redirect(request_uri)

@app.route("/login/callback")
def callback():
    code = request.args.get("code")

    google_provider_cfg = get_google_provider_cfg()
    token_endpoint = google_provider_cfg["token_endpoint"]

    token_url, headers, body = client.prepare_token_request(
        token_endpoint,
        authorization_response=request.url,
        redirect_url=request.base_url,
        code=code,
    )
    token_response = requests.post(
        token_url,
        headers=headers,
        data=body,
        auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
    )

client.parse_request_body_response(json.dumps(token_response.json()))

    userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
    uri, headers, body = client.add_token(userinfo_endpoint)
    userinfo_response = requests.get(uri, headers=headers, data=body)

    if userinfo_response.json().get("email_verified"):
        unique_id = userinfo_response.json()["sub"]
        users_email = userinfo_response.json()["email"]
        picture = userinfo_response.json()["picture"]
        users_name = userinfo_response.json()["given_name"]
    else:
        return "User email not available or not verified by Google.", 400

    user = User(
        id=unique_id, name=users_name, email=users_email, profile_pic=picture
    )
    if not User.get(unique_id):
        user = User(
            id=unique_id, 
            name=users_name, 
            email=users_email, 
            profile_pic=picture
        )
        db.session.add(user)
        db.session.commit()
    login_user(user)
    return redirect('http://localhost:4000/')

class Logout(Resource):
    def delete(self):
        if current_user:
            logout_user()
            return {}, 204
        return {"error": "401 Unauthorized"}, 401

api.add_resource(CheckSession, '/check_session', endpoint='check_session')
api.add_resource(Logout, '/logout', endpoint='logout')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember we imported current_user, login_user, and logout_user from the Flask-Login package, which saves us from writing each of these methods ourselves. The UserMixin added to the User model adds a number of properties and methods to our User model, including is_authenticated, which we use in the CheckSession route. Once we've gotten these four endpoints written, we can move to configuring the React front end of this process.&lt;/p&gt;

&lt;h3&gt;
  
  
  React Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;client&lt;/code&gt; folder&lt;/p&gt;

&lt;p&gt;Great news - configuring the React side of the application for Google login with OIDC is pretty simple. All of the authentication happens on the server-side in our Flask routes, so from the front end we really only need a few things.&lt;/p&gt;

&lt;p&gt;Ensure you've set up a ('/') home route on your front end. I configured my home route using React Router v6, but it is important that there is a home route configured for Google login with OIDC to redirect to.&lt;/p&gt;

&lt;p&gt;Let's create a Button component that will have our 'Login with Google' functionality.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Button.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function Button({ children, onClick }) {
    return (
        &amp;lt;button onClick={onClick}&amp;gt;{children}&amp;lt;/button&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next navigate to the component you'd like to use the Login with Google button in, and import and render the Button.&lt;br&gt;
&lt;code&gt;Component.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Button from './Button'
import google from '../images/google.png'

export default function Component() {
    function handleClick() {
        window.open("http://localhost:5555/login", "_self")
}
return (
    &amp;lt;div&amp;gt;
    &amp;lt;Button 
    onClick={handleClick} 
    children={
        &amp;lt;div className="flex gap-2 items-center justify-center"&amp;gt;
        &amp;lt;img src={google} alt="google-logo" className="h-7 w-7"/&amp;gt;
        &amp;lt;span&amp;gt;Login with Google&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;}
        /&amp;gt;
    &amp;lt;/div&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this component, I imported a Google logo image that I've added to my file and create my own Login button to mirror the Login with Google buttons I have seen using Tailwind CSS. The button CSS can be configured any way you'd like, the important part for utilizing Google login with OIDC is the handleClick() function.&lt;/p&gt;

&lt;p&gt;In the handleClick() function, we are navigating to the backend ('/login') route we wrote in our &lt;code&gt;app.py&lt;/code&gt; file, which starts the Google login OIDC authentication process. You may have to configure CORS to allow the application to open another window. The "_self" parameter opens the window in a new tab. Back in our &lt;code&gt;app.py&lt;/code&gt; ('/login/callback') route, our last line of code was:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt; ('/login/callback') route&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    return redirect('http://localhost:4000/')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we direct users to the ('/login) route from our React application with the handleClick() function, the ('/login') route authenticates the user, moves to the ('/login/callback') route, then if all goes well, redirects the user back to our front end ('/) home route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;When testing each step of this configuration, make sure to follow the error messages in the console. I also found it necessary to clear my browser cookies between changes to my code especially when coming across internal server errors. All of this code is configured to work in a local development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Resources
&lt;/h2&gt;

&lt;p&gt;This &lt;a href="https://realpython.com/flask-google-login/"&gt;article from Real Python&lt;/a&gt; was critical to my successful implementation of OIDC and Google in my Flask-React application. Best of luck with implementing Google login through OIDC!&lt;/p&gt;

</description>
      <category>google</category>
      <category>flask</category>
      <category>react</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Python Recursion Errors &amp; Serializer</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Mon, 05 Jun 2023 21:15:40 +0000</pubDate>
      <link>https://forem.com/jvaughn619/python-recursion-errors-serializer-2kh8</link>
      <guid>https://forem.com/jvaughn619/python-recursion-errors-serializer-2kh8</guid>
      <description>&lt;p&gt;I recently completed my first Flask-React application, a Spotify clone app called 'myTunes' that allows users to create unique playlists, add songs from my PostgreSQL database, then play those songs through linking to the Spotify web-browser. I felt like I had finally gotten the hang of one-to-many and many-to-many database model relationships - my database was seeded and rendering on the React front-end, but I noticed my initial fetch was taking longer and longer to complete. I figured it was a byproduct of pulling more data in from my backend routes and that I would continue to build my app and then research ways to make the fetch more efficient. I added one more route - a post route to add a Song instance to a Playlist - and suddenly my environment crashed and I saw a giant 'RECURSION ERROR' in my terminal. &lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Recursion
&lt;/h2&gt;

&lt;p&gt;Welp. This was the first time I'd ever experienced a recursion error, and it looked terrifying. I tried to scroll to the top of the error, but it seemed unending. Turns out, that's exactly what a recursion is - a function that calls itself from within the function. The important part of writing a recursion correctly is that the function must terminate at some point, otherwise it cannot run because it uses too much memory, processing power, or simply is just infinite. &lt;/p&gt;

&lt;p&gt;Writing recursions can be very helpful - for example, you may want to write a function that counts backward from some starting point and stops at 0. As long as the function can reach a termination point, recursive functions are perfectly acceptable to write and can be extremely efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursion in Model Relationships
&lt;/h2&gt;

&lt;p&gt;Rendering relational data is a prime environment for experiencing recursion errors.  For example, in the myTunes application I built, I designed a many-to-many relationship between my Playlist and Song models. I have simplified the models here to only include relevant information to solving the recursion error.&lt;/p&gt;

&lt;p&gt;Playlist Model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Playlist(db.Model):
    __tablename__ = "playlists"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    songs = db.relationship('Song', secondary=playlist_song, back_populates='playlists')

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    def __repr__(self):
        return f'&amp;lt;Playlist ID: {self.id} | Name: {self.name}&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Song Model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Song(db.Model):
    __tablename__ = "songs"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    artist_name = db.Column(db.String, nullable=False)

    playlists = db.relationship('Playlist', secondary=playlist_song, back_populates='songs')

    def __repr__(self):
        return f'&amp;lt;Song ID: {self.id} | Name: {self.name} | Artist: {self.artist_name}&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Join Table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playlist_song = db.Table('playlist_songs',
                          db.Column('playlist_id', db.Integer, db.ForeignKey('playlists.id'), primary_key=True),
                          db.Column('song_id', db.Integer, db.ForeignKey('songs.id'), primary_key=True))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Playlist and Song models are related through a join table, Playlist_Song. I pulled all of this data into my application through the /artists endpoint, invoking the Python method .to_dict() on each instance on the Flask side of app, then invoking .json() when rendering the data in a fetch request through my React front-end. This process of converting data objects into other forms to be transmitted is called &lt;strong&gt;serialization&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;As I continued to build out Flask endpoints, I noticed my fetch request on the React end was taking longer and longer to complete. Eventually, the dreaded recursion error hit and I frantically Googled and asked ChatGPT for help before taking a breath and remembering I could test instances of my models in the Flask shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flask shell
hello = Song(name="Hello", artist_name="Adele")
jams = Playlist(name="Jams")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating instances of a Song and Playlist, I tested the relationship and the .to_dict() method to ensure the .to_dict() method could successfully be invoked and return a dictionary object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello.to_dict()
{...} / Successful response /
jams.to_dict() 
{...} / Successful response /
hello.playlists
[] / Successful response as no playlists were assigned /
jams.songs
[] / Successful response as no songs were assigned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Single instances with no relationships were able to successfully convert to dictionary objects through the .to_dict() method. I next moved to testing multiple instances with relationships established on my seeded database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flask shell
playlists = Playlist.query.all()
songs = Song.query.all()
playlists[0].songs / Grabbed first playlist and listed all songs
[...] / Successful response with the songs I had related to the playlist
playlists[0].songs.to_dict()
RECURSION ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AHA! I scrolled back in my terminal to check the output from playlists[0].songs again and saw that in addition to outputting the 5 songs I had assigned to the playlist, each of those songs had a nested 'playlists' key that included the top level playlist, and that each of those nested 'playlists' keys had the songs nested within them again... When invoking .to_dict() on this structure, it produced a recursion error because it caused a NEVER ENDING nesting of data.&lt;/p&gt;

&lt;p&gt;I also tested this data the other way around - as songs.playlists instead of playlists.songs, and found another recursion error. I needed to find a way to exclude my database relating the data from each model endlessly to one another. Enter - SQLalchemy serializer mixin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serializer Mixin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/SQLAlchemy-serializer/"&gt;Serializer Mixin&lt;/a&gt; is a mixin that adds the .to_dict() method to model instances. This eliminates the need to define an explicit .to_dict() class method. It also allows the user to set rules for serialization so that certain relationships and columns can be EXCLUDED from the .to_dict() method, ideally avoiding the recursion error cause by Python trying to nest this relational data endlessly when serializing the data objects to another type. &lt;/p&gt;

&lt;p&gt;Serializer Mixin can be used by importing it from sql-alchemy. Here are the updated Playlist and Song models utilizing Serializer Mixin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sqlalchemy_serializer import SerializerMixin

class Playlist(db.Model, SerializerMixin):
    __tablename__ = "playlists"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    songs = db.relationship('Song', secondary=playlist_song, back_populates='playlists')

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    def __repr__(self):
        return f'&amp;lt;Playlist ID: {self.id} | Name: {self.name}&amp;gt;'

class Song(db.Model, SerializerMixin):
    __tablename__ = "songs"

    serialize_rules = ('-playlists', )

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    artist_name = db.Column(db.String, nullable=False)

    playlists = db.relationship('Playlist', secondary=playlist_song, back_populates='songs')

    def __repr__(self):
        return f'&amp;lt;Song ID: {self.id} | Name: {self.name} | Artist: {self.artist_name}&amp;gt;'

playlist_song = db.Table('playlist_songs',
                          db.Column('playlist_id', db.Integer, db.ForeignKey('playlists.id'), primary_key=True),
                          db.Column('song_id', db.Integer, db.ForeignKey('songs.id'), primary_key=True))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Song model, I specified rules to exclude '-playlists' from serialization. After upgrading my Flask database and reseeding, I opened the Flask shell and tested the same instances as before. This time, songs[0].playlists.to_dict() and playlists[0].songs.to_dict() successfully returned dictionary objects with no recursion errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing for Recursive Functions
&lt;/h2&gt;

&lt;p&gt;After finding the first recursion error in my code through testing instances of my seeded database in the Flask shell, I continued to test out each of the relationships I had built between my additional models: User, Artist, Song, and Playlist. In each case, when invoking .to_dict() on a model related to another, I ran into a recursion error. I added serialize rules to exclude each of the areas resulting in an error. Check out my GitHub repo for myTunes to see the &lt;a href="https://github.com/jessicavaughn619/phase-4-project-mytunes/blob/main/server/models.py"&gt;full models.py code&lt;/a&gt; to see all instances of serialize rules I needed to add.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;After adding the necessary serialize rules to each model, I started up my application using honcho (if you don't know about honcho, &lt;a href="https://honcho.readthedocs.io/en/latest/"&gt;check it out&lt;/a&gt; to run both front and back-end development environments with one command!) and not only did I NOT run into a recursion error, but my fetch data loaded quickly. I realized in hindsight that the other recursion errors I had built in through my models had not quite been problematic enough to bypass Python's recursion limit, but by eliminating the accidental-recursive functions my database instances were able to be serialized much more quickly and without unwanted nested data.&lt;/p&gt;

&lt;p&gt;While following through recursion errors can be daunting, I hope this guide helps take some of the mystery out of this error. Since solving my own recursion errors with Serializer Mixin, I have also found the &lt;a href="https://marshmallow-sqlalchemy.readthedocs.io/en/latest/"&gt;Marshmallow (de)Serialization library&lt;/a&gt; from SQL-Alchemy. I have yet to use this library, but it looks like another solution to serialization errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  myTunes Info
&lt;/h3&gt;

&lt;p&gt;If you're interested in checking out myTunes, here is my full &lt;a href="https://github.com/jessicavaughn619/phase-4-project-mytunes"&gt;GitHub repository&lt;/a&gt;! For the TLDR version of myTunes, check out my &lt;a href="https://youtu.be/DFA_5AwnnIw"&gt;walkthrough video&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>flask</category>
      <category>debugging</category>
      <category>recursionerror</category>
    </item>
    <item>
      <title>Tutorial: Setting Up a CLI Project Integrated with SQLAlchemy</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Tue, 02 May 2023 20:22:15 +0000</pubDate>
      <link>https://forem.com/jvaughn619/tutorial-setting-up-a-cli-project-integrated-with-sqlalchemy-4f3c</link>
      <guid>https://forem.com/jvaughn619/tutorial-setting-up-a-cli-project-integrated-with-sqlalchemy-4f3c</guid>
      <description>&lt;p&gt;I recently built my first Command Line Interface project utilizing Python, SQLAlchemy, and Alembic. The most challenging parts of this project were setting up my initial file structure and determining what code needed to belong in each file. My hope is this tutorial will save other new Python coders time when developing their own CLI projects and can serve as a starting point for developers building their first CLI! I am sharing code snippets from my project and have included the GitHub repo to the full code at the end of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Considerations
&lt;/h2&gt;

&lt;p&gt;Applications can be most effective when they solve real-world problems. Before starting my project, I identified an issue I had as a music teacher - tracking locker and musical instrument assignments for my high school students - and then designed a CLI project to address this need.&lt;/p&gt;

&lt;p&gt;When building a CLI connected to a database, one of the first considerations are the tables and relationships the database will consist of. For my music locker room database, I needed three tables: Lockers, Instruments, and Students. I determined these tables would be related through a many-to-many relationship through the Student table, as a Student could have many instruments and many lockers, but a Locker and an Instrument could each only have one Student assigned. &lt;/p&gt;

&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;

&lt;p&gt;I set up my project with the following folder tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa75c0da2nzz1llj8diah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa75c0da2nzz1llj8diah.png" alt="Tree depicting file structure for CLI project in Python"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the db folder, I created 3 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;debug.py (for testing my instances)&lt;/li&gt;
&lt;li&gt;models.py (where to write my table classes)&lt;/li&gt;
&lt;li&gt;seed.py (where to create all of my instances to seed the database)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The top level bando.py file is where I wrote all of my actual CLI code. I utilized the subfunctions folder and additional .py files within this folder to refactor out my CLI code later on.&lt;/p&gt;

&lt;p&gt;The db folder is where I created my Alembic migrations, and the db/models.py file is where I created all of my database table models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Imports
&lt;/h2&gt;

&lt;p&gt;Once establishing this initial file structure, I opened up my project and installed SQLAlchemy and Alembic through pipenv:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pipenv install sqlalchemy alembic&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Later, I imported additional packages to help me build out my CLI functionality, including Inquirer, Pandas, Faker, and Redux.&lt;/p&gt;

&lt;p&gt;Next, I ran the following command to enter the virtual environment:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pipenv shell&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Database Set Up
&lt;/h2&gt;

&lt;p&gt;In order to utilize alembic to manage migrations, I needed to add some code to the db/alembic.ini and db/migrations/env.py files generated when I installed alembic. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;alembic.ini&lt;/em&gt;&lt;br&gt;
Line 63:&lt;br&gt;
&lt;code&gt;sqlalchemy.url = sqlite:///band_lockers.db&lt;/code&gt;&lt;br&gt;
This line needed to be changed to the name of the database file I wanted to set up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;env.py&lt;/em&gt;&lt;br&gt;
After line 20 add:&lt;br&gt;
&lt;code&gt;from models import Base&lt;br&gt;
target_metadata=Base.metadata&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next I set up my tables using the db/models.py file. After creating each table, I ran the following commands in my terminal:&lt;br&gt;
&lt;code&gt;alembic autogenerate revision -m "message here"&lt;/code&gt;&lt;br&gt;
followed by:&lt;br&gt;
&lt;code&gt;alembic upgrade head&lt;/code&gt;&lt;br&gt;
Each revision created a migration version in the db/migrations/versions folder. Utilizing Alembic for migrations can be really helpful in case the need to revert to a previous revision arises.&lt;/p&gt;

&lt;p&gt;After running the first migration, a new .db file should be added to the tree. This is the file to reference when instantiating any other sessions (like in the top level .py file where I set up my CLI!)&lt;/p&gt;

&lt;p&gt;After setting up my tables (and relationships utilizing backref) in the models.py file, I moved to the seed.py file to create instances of my classes and seeded my database.&lt;/p&gt;
&lt;h2&gt;
  
  
  Seeding the Database
&lt;/h2&gt;

&lt;p&gt;SQLAlchemy relies on a couple of imports: Session and create_engine&lt;/p&gt;

&lt;p&gt;Here is an example of how I set up my seed file to use SQLAlchemy:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;seed.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sqlalchemy import create_engine
from sqlalchemy.orm import Session

engine = create_engine("sqlite:///band_lockers.db")
session = Session(engine, future=True)

_Create instances of classes here..._

session.close()
session.commit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instantiating a CLI
&lt;/h2&gt;

&lt;p&gt;In the bando.py file, I imported create_engine and Session from SQLAlchemy again and set up a Cli class (which included all of my logic to run my CLI!).&lt;br&gt;
I instantiated my Cli class in the if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;" block like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if __name__ == "__main__":
engine = create_engine("sqlite:///db/band_lockers.db")
session = Session(engine, future=True)
Cli()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block of code runs the defined Cli class when the session is instantiated - aka when the file is run! &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Beyond this point, the CLI class can be defined to include whatever logic the developer would like. I chose to have my logic complete full CRUD operations to allow the user complete control of the database from the command line. Feel free to peruse my project code to see examples of how I handled this logic!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jessicavaughn619/band-lockers" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/jzYhgUnqOOo" rel="noopener noreferrer"&gt;Band Locker CLI Walkthrough&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>sqlalchemy</category>
      <category>commandlineinterface</category>
      <category>webdev</category>
    </item>
    <item>
      <title>State Information Flow in React</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Wed, 01 Mar 2023 19:18:06 +0000</pubDate>
      <link>https://forem.com/jvaughn619/passing-state-as-props-in-react-3f9e</link>
      <guid>https://forem.com/jvaughn619/passing-state-as-props-in-react-3f9e</guid>
      <description>&lt;h2&gt;
  
  
  What is State?
&lt;/h2&gt;

&lt;p&gt;State is dynamic data in a React application. React re-renders child components when state changes. State should only be used for data that is expected to change throughout the life of the component. It should also be used sparingly, as it can become difficult to track throughout complex applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  useState
&lt;/h3&gt;

&lt;p&gt;In order to utilize state in an application, you must import the useState hook from React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The useState hook returns an array with two variables, a reference to the current state and a callback function that can be used to update state. You can pass an initial value for state into useState as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// initial value for state is "" //
const [state, setState] = useState("");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever the callback function, or setter function, is called, React re-renders the child components that are affected by change in state. React's documentation states to always use the setter function to update the value of state. Never directly assign the value of the state variable, except upon initialization. &lt;/p&gt;

&lt;p&gt;State updates asynchronously, therefore if you are using the current value of state to update state, you must use the callback syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [count, setCount] = useState("0");

// incorrect //
setCount(count + 1);

// correct - uses callback syntax //
setCount((count) =&amp;gt; count + 1);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about the useState hook in the React docs &lt;a href="https://reactjs.org/docs/hooks-state.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing State from Parent to Child Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Information Flows Down
&lt;/h3&gt;

&lt;p&gt;State can be passed to child components as a property in the same way we pass other properties . The useState hook should be imported and state should be declared at the highest common parent component level and then passed to the child components that need access to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Parent //
import React, { useState } from "react";

function Parent() {
const [count, setCount] = useState("0");

return (
&amp;lt;Child 
count={count}/&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the count variable destructured from useState is being passed down as a prop to the Child component. Just like with other kinds of props, the Child component needs to take in this prop and can then utilize it. State variables can be passed down to multiple child components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing State from Child to Parent Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Information Flows Up
&lt;/h3&gt;

&lt;p&gt;When passing state up from a child component to a parent, we must still initialize state at the highest parent component level. In order to pass state up from the child component, we pass down a callback function from the parent component as a prop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Parent //

import React, { useState } from 'react';

function Parent() {
const [search, setSearch] = useState("");

function handleSearch(e) {
setSearch((e) =&amp;gt; e.target.value) 
}

return (
&amp;lt;Child 
search={search}
onSearch={handleSearch}/&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Child //

import React from 'react';

function Child({ search, onSearch ) {
return (
&amp;lt;input 
type="text" 
value={search}
onChange={onSearch}&amp;gt;&amp;lt;/input&amp;gt;
)}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, search is being passed from the Parent component to the Child component. The onSearch property is passing down a callback function, handleSearch, to the Child component. When the input text in the Child component is changed, onSearch sets the value of search to e.target.value at the Parent component level, which is where our state is held. All of the child components of Parent are then re-rendered with the updated state. Passing state up as a callback function ensures other components utilizing state are also updated and that only one value for state is held.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Destructuring Arrays &amp; Objects in JavaScript</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Wed, 01 Feb 2023 16:17:02 +0000</pubDate>
      <link>https://forem.com/jvaughn619/destructuring-arrays-objects-in-javascript-1m36</link>
      <guid>https://forem.com/jvaughn619/destructuring-arrays-objects-in-javascript-1m36</guid>
      <description>&lt;p&gt;The first time I approached a lab with the deliverable of 'de-structuring objects and arrays' I spent the better part of an hour just trying to complete the very first step - assigning a variable and pulling the values out I was looking for. The syntax didn't make a ton of sense to me and I wasn't sure why I even would need to 'destructure' something in Javascript. Recently I revisited the same lab and was able to complete all seven deliverables in minutes. Its pretty amazing how taking time away and revisiting a concept can solidify it in your mind - as a beginner in web development it is so important to remember to step away from a concept when it is overly frustrating and come back to it after a little while. Concepts become more familiar as we circle back to them, and over time we can deepen the level of complexity we approach a concept with. As I reflected on my experience returning to the same concepts multiple times, it reminded me of a very familiar concept in education called spiral curriculum. &lt;/p&gt;

&lt;h1&gt;
  
  
  What Is Spiral Curriculum?
&lt;/h1&gt;

&lt;p&gt;In addition to learning to code, I have been a teacher for the past eight years. I pursued my masters degree in education and have always been incredibly curious about how people learn. Spiral curriculum, a cognitive theory coined by Jerome Bruner in 1960, is curriculum which reinforces key concepts through revisiting the same content multiple times with deepening layers upon each revisit. You can read more about Bruner and spiral curriculum &lt;a href="https://files.eric.ed.gov/fulltext/ED538282.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In music education (my area of speciality) this might look like introducing a new musical concept, like phrasing, with a simple definition. The next time the concept is addressed, some aural examples of good and bad phrasing are provided. Next, students are taught to imitate or try performing these examples. When the concept is introduced again, students might be taught how simple cadences affect phrases and help determine how to phrase appropriately. Way down the line, music students in college learn to write their own cadential structures to communicate appropriate phrasing in their own compositions. Each time the concept of phrasing is explored, the layers of complexity deepen eventually providing the student with a broad and deep understanding of the concept. Comparing the initial introduction to phrasing to the final composition example, it's clear that the depth of understanding of the concept of phrasing is more rich.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spiral Curriculum and Coding
&lt;/h2&gt;

&lt;p&gt;As a novice coder, most of the concepts I am learning about are brand new to me. As I revisit concepts, I can achieve more complex deliverables because the syntax and uses are more familiar with each application. &lt;/p&gt;

&lt;h1&gt;
  
  
  Destructuring Assessment
&lt;/h1&gt;

&lt;p&gt;Destructuring assessment is a JavaScript ES6 expression which allows values from arrays and properties from objects to be defined into variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Destructuring an Array
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l3p1y1ylg68wtltoyok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l3p1y1ylg68wtltoyok.png" alt="Image description" width="800" height="146"&gt;&lt;/a&gt;&lt;br&gt;
In the example above, the constant 'dogs' is assigned to an array of four dog names. On line 3, each value of the array is 'destructured' on the left side of the expression, assigning a variable to each of the dog names from the array. Each new variable assigned on the left is assigned the value from the same index position from the array. (Ex. "mix" is in index position 0, therefore it is assigned the value of "Mandy", which is also in index position 0).&lt;/p&gt;

&lt;p&gt;Any variables can be assigned to the initial values from the array. If more variables are assigned than elements in the array, the additional variables are 'undefined'. See example below.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfido1bf6gcl8688d8ty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfido1bf6gcl8688d8ty.png" alt="Image description" width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next example, I destructured the dogs array to assign each dog name with a cuteness rating. Now both variables 'terrier' and 'supercute' are assigned the value 'Olivia'.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2a617w3ftl6rmx45cps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2a617w3ftl6rmx45cps.png" alt="Image description" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Destructuring an Object
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8jiz065py5mzfd7zdct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8jiz065py5mzfd7zdct.png" alt="Image description" width="800" height="216"&gt;&lt;/a&gt;&lt;br&gt;
An object's keys can be destructured as variables on the left side of the expression. The keys must match the original keys from the object. If I try to rename the key while destructuring, it returns 'undefined'.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6bcpu0jdzni4qcj2ufr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6bcpu0jdzni4qcj2ufr.png" alt="Image description" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the MDN docs for destructuring assessment &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Uses for Destructuring Assessment
&lt;/h1&gt;

&lt;p&gt;Destructuring allows the developer to assign multiple variables in one line of code. It also prevents having to reference values using dot notation, such as dogs.breed or dogs.favoriteThing. Instead, developers can reference the variables assigned while destructuring. This helps keep code clean and clear for both the developer and anyone reading the code. &lt;/p&gt;

&lt;h1&gt;
  
  
  Closing Thoughts
&lt;/h1&gt;

&lt;p&gt;I am just starting to familiarize myself with React components for the next phase of the program I'm working on. In React, destructuring is essential for passing props, or properties, between components clearly so that both the developer and anyone reading the code can see which properties are being passed between components. I am excited to see the impact of spiral curriculum on my understanding of destructuring as I visit the concept again through React.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloudcomputing</category>
      <category>kubernetes</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>JavaScript forEach() &amp; Building Elements</title>
      <dc:creator>Jessica Vaughn</dc:creator>
      <pubDate>Tue, 31 Jan 2023 22:57:17 +0000</pubDate>
      <link>https://forem.com/jvaughn619/javascript-foreach-building-elements-hl0</link>
      <guid>https://forem.com/jvaughn619/javascript-foreach-building-elements-hl0</guid>
      <description>&lt;p&gt;I recently built my first single-page project using JavaScript - an application called Wufr. Users can swipe left or right on their favorite dog images pulled from an API. By swiping right, users can save images of dogs into their favorites. If you are interested in reading more about this project or utilizing Wufr, please check out my &lt;a href="https://github.com/leopards4life/phase-1-project-wufr" rel="noopener noreferrer"&gt;Wufr GitHub repository.&lt;/a&gt; You can also check out the walkthrough &lt;a href="https://youtu.be/WAt56Ji8z8I" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I considered the best method to render the user's favorite dogs, the JavaScript forEach() method stood out as a great option to iterate through the array of favorite dogs created by each user when they 'swiped right' on their favorite dogs and then pass a callback function to render each dog image. &lt;/p&gt;

&lt;h2&gt;
  
  
  For Loop vs. forEach()
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Loop
&lt;/h3&gt;

&lt;p&gt;For loops are excellent for iterating over arrays and elements and executing a block of code. A break statement allows the code to 'break' out of the loop and stop the effect of the looping code at a designated point. For loops are more efficient performance-wise than forEach(), but generally require more code. If you're looking to execute a block of code multiple times, especially if the number of times is known, consider using a for loop. You can read more about for loops &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kwmb2ibjuyltmib0lfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kwmb2ibjuyltmib0lfw.png" alt="Image description" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  forEach()
&lt;/h3&gt;

&lt;p&gt;The forEach() method iterates through each element in an array and passes a callback function on each element. forEach() is a great option if you are looking for a method to iterate through each item one time. As forEach() accepts a callback function, developers can write with more brevity than when using a traditional for loop, where each line of code must be enumerated.  forEach() returns undefined, even if the callback function passed in has a return statement, therefore forEach() is typically utilized to achieve side effects rather than to return anything.&lt;/p&gt;

&lt;p&gt;forEach() iterates through elements in an array in ascending order by index. The method requires an array or element to be passed in and allows the starting index position to be specified. The forEach() method does not mutate the original array, but does allow for callback functions to mutate the array. The initial length of the array is saved as forEach() is called, therefore the method will not iterate past the initial length of the array even if the callback function mutates the original array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foz1qu56eepu9kk60asqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foz1qu56eepu9kk60asqv.png" alt="Image description" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  forEach() &amp;amp; Building Elements
&lt;/h2&gt;

&lt;p&gt;I decided to use forEach() to render favorite dog images on Wufr. This allowed me to manipulate the DOM by creating a new image element, set image attributes, add an event listener to each dog as it was created, and finally to append the dog image to the DOM in the favorites container, all within a callback function. With a small amount of code, I was able to execute this for each favorite dog image in my array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjoxyx99epmjpa9m2ijb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjoxyx99epmjpa9m2ijb.png" alt="Image description" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, I wanted my code to run the exact same way for each dog in my dogs array. The total number of elements in my dogs array is dependent on how many favorite dogs the user had saved, and since I did not need to utilize a break statement to exit my block of code at some point, forEach() seemed like the best fit for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting forEach() in Wufr
&lt;/h2&gt;

&lt;p&gt;While building Wufr, I initially set my favorite dogs variable to an empty array. Then I called forEach() on the array and passed in my callback function with an additional step - trying to push a new dog into my dogs array. I spent quite a bit of time trying to figure out why forEach() was not rendering any dogs images until I had added a second dog to my dogs array, meaning I had to add a dog to my favorites a second time to see the first dog rendered. The functionality was as if my application was rendering one dog behind each dog I swiped right on. I was not receiving an error message, but my application was not functioning as expected with push() as part of the forEach() callback function.&lt;/p&gt;

&lt;p&gt;After reading through the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" rel="noopener noreferrer"&gt;MDN documentation&lt;/a&gt; on forEach() I realized forEach() was saving the initial length of my array, and even though my callback function was mutating the array, this mutated array was not being passed into forEach() until the second time I called forEach() and the array already had a length of 1 element. In order for forEach() to iterate and pass a callback function to elements in the array, the array must have at least one element in it.&lt;/p&gt;

&lt;p&gt;After creating a second function to handle a post request to my db.json file and push my new favorite dog into my dogs array, forEach() rendered all of my favorite dogs as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;forEach() is an incredibly useful JavaScript method which should be considered when iterating through arrays and passing some side effects to each element. It allows the developer to shorten their syntax and to clearly demonstrate what is happening in their code through utilizing a callback function. As you decide whether to use this method, keep in mind that forEach() is a non-destructive method and you will need to utilize other functions to handle any changes to the array you are iterating through.&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
