Welcome to my Blog App (with CRUD operations and automated testing). This App will be using the MERN stack, and was made to show my experience and understanding working with a NoSQL database management system, like MongoDB.
Feel free to fork and/or follow along.
What I recommend is to fork it so that you have a working copy, and go ahead and, duplicate it and git clone <link-to-repo>
the duplicate.
That way, you're free to experiment a bit on not only your own repo(s), but also on your own machine at home / school / where ever.
However you go about it, this will give you a simple MERN-stack Blog App that's got fully operational CRUD commands, and working API endpoints.
Here's some screenshots of Postman (which is free, and you'll want to download here, if you don't already have it + watch a YouTube tutorial or two, to familiarize yourself with it. Super-simple, but also going to feel impossible, if you don't know how to use it).
Initial format for your JSON object:
{
"title": "Blog Post's Title",
"body": "The actual Post itself. All the Headings, words, sentences, paragraphs, etc.\n\n##Have Fun With It\n\nI just used escape characters, or, if I \"needed\" to add-in certain formatting, I just added it in, um, in here.\n\n### Maybe I Wanted To Create A Heading?\n\nThen that's what I did.",
"image": "IMGurlsbasicallyfrom.unsplashes-api.com/photo/12345=numbers-and-stuff"
}
The names for the CRUD Commands in Postman differ slightly:
So, I used Postman (as one does) to test out my API + the functions that handle different aspects of my CRUD operations:
getAllBlogPosts()
createNewBlogPost()
getBlogPostById(id)
updateBlogPostById(id)
deleteBlogPostById(id)
Before hitting 'Send':
And, after hiting 'Send', it gets it's id returned:
You can see the 'id' highlighted there (above).
Change the url (i.e. the API endpoint) in Postman that you're sending to:
localhost:3001:/api/blogs/<id number>
Updated part highlighted.
Note: you include the entire JSON object (i.e. "title", "body", and "image" url) in the Update / PUT request as well.
I created some garbage Post, for the purpose of testing out the 'deleteBlogPostById' function:
No JSON object needed for DELETE, just the API endpoint url and the 'id' number of the Blog Post that you want to Delete.
Here's the API endpoint again (including the prior successful POST's id), similar to how we did it with PUT and the GET (by id):
And then here(below) is the Success message, showing that we've successfully deleted the Post:
So, there you have it, Success messages (i.e. the '200 OK' response back) for POST, GET, PUT, and DELETE.
Using this code as a template, you should have a working MERN CRUD Blog app 'starter-kit', at the ready.
You have my permission to go make something amazing.
Gotta love acronyms.
Seriously. If you're going to be a Developer:
You've Got to Love Acronyms, or, "YGtLA" (is what I always say).
Ok, I made that one up.
However, peep these, my friend, they're all used here:
OOP.
SOLID.
Worth reviewing?
The SOLID principle, which you may have heard when reading about / being taught Object-Oriented Programming principles. It's really 5 Principles that help to keep software systems scalable and easier to maintain.
S - The Single Responsibility Principle encourages each class or module to have only one reason to change, making it easier to understand and maintain.
O - The Open/Closed Principle suggests that entities should be open for extension but closed for modification, allowing new functionality to be added without altering existing code.
L - The Liskov Substitution Principle promotes the use of inheritance in a way that derived classes can be substituted for their base classes without affecting the correctness of the program.
I - The Interface Segregation Principle states that clients should not be forced to depend on interfaces they don't use.
D - The Dependency Inversion Principle advocates depending on abstractions rather than concrete implementations, enabling flexibility and decoupling between different components of the system.
Yeah, (M)ongoDB + (E)xpress.js + (R)eact.js (N)ode.js = MERN
Make sense?
What's that you say? You 'have a 6th sense, and that sense is: the overwhelming feeling that you're crazy to think you'd ever understand this, and yes, it does increase that sense' for you?
Heh, I can relate.
You're probably not "crazy", just ignorant.
And inexperienced. Well, and... idk if it's something that you ate(?), but you kinda smell funny too. Don't forget the food chain!
No problem--all fixable. Keep studying. Actually read the docs. Keep practicing, searching online for answers, find a mentor, take a shower (although, if you're being mentored in-person, maybe take the shower prior? Don't be afraid: you can control the heat of the water, and you'll have some of your best thinking sessions in there!).
There's no "quick" fix, but there is a "quickest" fix.
Keep after it. Hunt down 'understanding' as if it was meat, and your Family was starving. And, I mean, if you want me to make that analogy, it's actually not that far off, right?
Or... you might just be stupid crazy.
But hey, the good news?
Knowing is half the battle!
And even that's ok.
It'll just take a little longer to 'get it'.
But 'get it' you shall, my friend.
The MERN stack will allow you to become a developer superhero aka a full stack developer.
If you're ready to get started, we need to make sure we've got a few things installed:
node -v
npm -v
mongodb -v
mongoose -v
If not, go ahead and npm install <whatever-you-don't-have>
If you don't have Node.js, however, you may wish to visit the npm docs here first.
I also used nodemon for development, and kept it's default for auto-restart of the node app, so I could troubleshoot and console.log right into my Terminal.
npm install nodemon
package.json
file" "scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "mocha --timeout 10000"
},
"homepage": "https://github.com/ericsecution/mern-crud-blog#readme",
"dependencies": {
"dotenv": "^16.3.1",
"express": "^4.18.2",
"mongodb": "^5.7.0",
"mongoose": "^5.13.20",
"npm": "^9.8.1"
},
"devDependencies": {
"chai": "^4.3.7",
"chai-http": "^4.4.0",
"mocha": "^10.2.0"
}
Yeah, as you can see above, I'm using Chai for Testing - Click Here for more info:
npm install chai
What we're doing, essentially, is using the Mocha testing framework
npm install mocha
And so that adds in Mocha along with the Chai assertion library, which is configured to be used with the chai-http plugin.
npm install chai-http
In order to keep my testing data separate from my App data (and since MongoDB only allows one database per Project for Free-tier Atlas accounts), I created a separate Collection within my MongoDB Atlas cluster, ests_dev_data
.
I then essentially mirrored the flow of data, but for testing purposes (with the aim to keep it separate both within the codebase, as well as the database).
That "flow" goes from:
That being said, we have a ./models/TestDevData.js
file that provides schema for the Test Blog Posts.
Then, we utilize the Mongoose library's functions (i.e. find()
, create()
, findById()
, findByIdAndUpdate()
, and findByIdAndDelete()
) within the ./services/TestDevDataServices.js
file, using Object Data Modeling (ORM) which assists Node.js in communicating with the MongoDB database (specifically, the 'tests_dev_data' Collection, in this case, that I needed to 'Create' via the 'Collections' tab over in my MongoDB Atlas account).
From there, you can start with the tests that I've created and/or just add more (see their websites above, for a number of different examples and walk-thrus), but for a basic setup, this should allow you to create your tests as you go.
If you add-on new features for your Blog app, add-on the Test(s) as well.
Simple and easy enough, right?
You don't have to do this, but (as mentioned already) I also created an Atlas account (it's free--or, rather, there's a free option, which is what I used). If you want to as well, just head over to MongoDB Atlas, and then create an account and a database "cluster", in order to use their server to host the database.
Ahh yes, the MERN stack. Simple, but there's a lot that you could learn about it, so it's kind of a best-of-both-worlds in that it's easy to get started, and there's a lot of room for growth, increased skill, and a lot you can do with it.
Maybe that's a "best-of-all-worlds" type situation? π€
Idk.
Anyway, it came about as a (relatively) modern solution to the object-oriented design foundation of a 3-tier architecture in software development--which (you guessed it!) has π₯ ... 3 tiers, made up of our logical layers.
Good question. If you believe the majority of people on dev forums, you'll sometimes limit your perspectives to one comment supported by more than a handful of other people:
"... everyone I've met in software world uses these two terms interchangeably as if they are exactly the same."
Unless you're addicted to the derisive laughter of a nerd engineer, you probably don't want to quote that in your next post-work Slack sessions, trying to sound smart.
What good will sounding smart do either of us anyway?
Better just to keep plugging away, be humble, ask questions, ask for help, learn, help others, build up our skills and understanding, and then be smart, ya?
I've heard it described (paraphrasing, so dyor, study code, style guides, read books, etc) as:
Layers refer to the logic that's literally in your code, how it's structured: folders, files, functions--a logical separation of the code itself.
These, of course, all exist within the same application, yeah?
Tiers represent the physical machines or structures that code is fed through:
Layers: Consider a stage with different structured set pieces as backdrops, one stacked behind one another. Each backdrop (or layer) sets a different scene, but they are all part of the same performance's stage setup.
Tiers: Now, think of multiple stages in a theater complex. Each stage (or tier) hosts a different play or performance, operating independently of the others.
Yes, it's true. I do love PostgreSQL. PERN's cool too. π
However, with postgres, we're not exclusive. Feel free to fire up your pgAdmin4 and have at it.
We have, ahem, an open relationship. Very, very open. π
What? No! π¦ Where'd you get that?
I mean, I like working with open-source applications.
I chose MongoDB here because it's a solid open-source app that also works well with Atlas, MongoDB's cloud-based database service. Atlas is a fully-managed system that allows us to deploy, manage, and scale MongoDB databases on the cloud (i.e. without needing to setup and maintain a server to handle hosting for the database).
Well, I'd suggest you go velcro, but... that might be a little dangerous. Let's stick with laceless or just flip-flops for now.
In the meantime, check out The MongoDB FAQ and start here.
When you're done there, go here.
π π π π π
Did you read through all of it?
No? You just, 'Skimmed some, kinda got the gist'...?
π€¨
Alright, no worries.
We'll learn (mern2earn) by doing.
MERN is a popular full-stack combination of technologies that have a proven track-record of success--meaning: there's a lot of apps built this way out there. My choice, contrary to my usual M.O., isn't very creative.
my goal is to empower us (you and me)--if you're a builder(, creator, developer, etc)--to both:
Easy enough?
this App should be practical enough too, ya?
Since I began developing (more seriously) last year (incl attending and graduating from a Full-Stack Developer Bootcamp), I've been on a non-stop learning endeavor.
This is not uncommon for any developer (i.e. the need for continual self-devlopment, in addition to gaining understanding), and that would've never been possible without the help of other (super-patient) people.
Someone taught me how to do this, and so I can hopefully pass that along to you as well.
The good news is that, because the MERN stack is so popular and prevalent, it's not difficult to locate that (often-required) help.
I'm also available here or over on LinkedIn, if you want to chat about this Project, the MERN stack, development (use cases, crypto, gamedev, etc) and/or web 3.
Let's get this party started and ...
"Learn to MERN before we learn to earn." π€
GitHub: ericsecution
LinkedIn: Eric Mangin
Gmail: EricPaulDev@gmail.com
It'll ask you what 'type' of application you're building, with the drop-down options being:
Other
You can select your Pricing / Performance tier, but for most of us, for now, just start out with the ($Free-99) "M0" tier, which has less storage, slower (shared) access, and so on.
You can also select your 'Provider':
I went with AWS for no other reason than it was already selected as the default.
You can also select your location (i.e. where your data center is housed).
I left the default / 'Recommended' option selected here as well (for me, the Eastern U.S., in Virginia).
Tags opt: scroll down (below) to the Resource Tags section, if you want a list of potential resource tags:
Congratulations! π
π You've setup your MongoDB Atlas cluster (holla!).
At this point, you should be seeing a side-menu with various options under these 3 headings:
These options will allow you to manage different aspects of your MongoDB Atlas setup, including configuring the cluster, accessing logs, managing users, setting up backups, etc.
LearnMERN2Earn | MongoDB Atlas Cluster Resource Tags |
---|
Key | Value |
---|---|
users | resource_users |
authors | resource_authors |
posts | resource_posts |
comments | resource_comments |
categories | resource_categories |
tags | resource_tags |
likes | resource_likes |
sharing | resource_sharing |
user_profiles | resource_user_profiles |
settings | resource_settings |
seo | resource_seo |
analytics | resource_analytics |
headers | resource_headers |
pages | resource_pages |
sidebar | resource_sidebar |
footer | resource_footer |
menu | resource_menu |
rss_feed | resource_rss_feed |
forms | resource_forms |
search_index | resource_search_index |
popups | resource_popups |
chatbot | resource_chatbot |
breadcrumbs | resource_breadcrumbs |
archive | resource_archive |
reverse_chronological | resource_reverse_chronological |
datetime | resource_datetime |
keywords | resource_keywords |
ui | resource_ui |
excerpts | resource_excerpts |
related_posts | resource_related_posts |
featured_posts | resource_featured_posts |
wysiwyg_editor | resource_wysiwyg_editor |
newsletter | resource_newsletter |
plugins | resource_plugins |
themes | resource_themes |
faqs | resource_faqs |
guest_bloggers | resource_guest_bloggers |
contests | resource_contests |
products | resource_products |
events | resource_events |
stats | resource_stats |
quotes | resource_quotes |
charity | resource_charity |
memes_gifs | resource_memes_gifs |
videos | resource_videos |
quizzes | resource_quizzes |
guides | resource_guides |
giveaways | resource_giveaways |
polls | resource_polls |
games | resource_games |
You can do this however, you want. Generally, it's a good idea not to put your passwords, secret keys, ATM PIN #'s, etc out there, for everyone to see, ya?
If you're just creating a copy of this on your local machine, you can setup your machine's OS method for environment variables, or, a common way it's done in the MERN stack Developer world (i.e. if you're gonna git push
this could into a public / online repository) is to use a package like dotenv (created by the Developer, Mot).
If you want to go that route (which is what I did), you go into your Terminal and type:
npm install dotenv
πΊ Mot shows the basics of dotevn in 2 minutes β²οΈ
π΄ββ οΈ Nonconformist Propaganda Machine - dotenv π£οΈ
Alright, so anyway, you create your .env
file (it's literally named just that--kinda like your .gitignore
file, right? Right: and go and check that file and make sure you're '.gitignoring' your .env
extension(s) / file as well, before your next git add
, etc, or you'll feel like a clown π€‘ who races donkeys π« for a living, because you'll have just uploaded all of the passwords you were attempting to obscure).
In my code, I'm connecting to my MongoDB Atlas cluster inside of the mongoose.connect()
, and so all I want to do is slightly modify that link with this:
MONGODB_URI=mongodb+srv://<myusername>:<mypassword>@learnmern2earn.uptbe18.mongodb.net/?retryWrites=true&w=majority
<username>
with your MongoDB Atlas username.<password>
with your MongoDB Atlas password.