I already solved the problem but now IT is back. I want to save new artist to the website or edit them but now its like the application doesnt connect to the DB but it is! I checked.
const
express = require('express'),
router = express.Router(),
Post = require('../models/post');
// Define which ImageTypes are avaiable to upload
const imageMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'];
// All admin Routes
router.get('/', async (req, res) => {
renderNewPage(res, new Post())
})
// New Route
router.get('/create', (req, res) => {
res.render('admin/createPost/index', {
layout: 'layouts/admin',
// Defined in models/post, gets variables
post: new Post()
});
})
// New Post create
router.post('/', async (req, res) => {
const post = new Post({
// get information from sended new Post (above) and defines variables to use in ejs files
surname: req.body.surname,
name: req.body.name,
bio: req.body.bio,
birthday: req.body.birthday,
technic: req.body.technic,
techPricerangeFrom: req.body.techPricerangeFrom,
techPricerangeTo: req.body.techPricerangeTo
})
// set FilePond saving files to DB
saveProfilpic(post, req.body.profilpic)
try { // await for new post to safe
const newPost = await post.save();
res.redirect('admin');
} catch {
renderNewPage(res, post, true)
}
})
//? Singe Artist Show, Edit, Upate, Delete
// Create single artists page
router.get('/:id', (req, res) => {
res.send('Show Artist' + req.params.id)
})
// Edit artist
router.get('/:id/edit', async (req, res) => {
try {
const findPost = await Post.findById(req.params.id)
res.render('admin/edit', {
layout: 'layouts/admin',
post: findPost
})
} catch {
res.redirect('/admin')
}
})
// Update artist text
router.put('/:id', async (req, res) => {
let post;
try {
post = await Post.findById(req.params.id)
post.surname = req.body.surname,
post.name = req.body.name,
post.bio = req.body.bio,
post.birthday = req.body.birthday,
post.technic = req.body.technic,
post.techPricerangeFrom = req.body.techPricerangeFrom,
post.techPricerangeTo = req.body.techPricerangeTo,
post.profilpic = req.body.profilpic
await post.save();
res.redirect(`/admin`);
} catch {
if (post == null) {
res.redirect('/admin')
}
else {
res.render('admin/edit', {
layout: 'layouts/admin',
post: post,
})
}
}
})
// Define functions
async function renderNewPage(res, post, hasError = false) {
// Implement all Posts (artists) in the DB
try {
const posts = await Post.find({}).collation({ locale: 'en', strength: 2 }).sort({ name: 1 }) // wait and find all post and sort my name
const params = {
layout: 'layouts/admin',
posts: posts, // take all posts from await Post.find({}) and overrides the updates the posts
}
if (hasError) params.errorMessage = 'Ein Fehler ist aufgetreten'
res.render('admin/index', params);
} catch (err) {
res.redirect('/');
}
}
// func for dave files via filepond
function saveProfilpic(post, profilpictureEncoded) {
if (profilpictureEncoded == null) return
const profpic = JSON.parse(profilpictureEncoded);
if (profpic != null && imageMimeTypes.includes(profpic.type)) { // If the file is a json obj & from the type image (jpg, png)
post.profilpic = new Buffer.from(profpic.data, 'base64') // Buffer.from(where, how)
post.profilpicType = profpic.type
}
}
module.exports = router;
all types in the model/post file are Strings.If I want to change something it redirects me to /admin, what means its a error. I got all latest packages (express, mongoose, ...)
I found your answer as I was working on the same tutorial, so I'm still quite new to this, but in my case the problem was related to having a missing '=' in the index page view.
Do you have the '=' character within the <% %> part so that the id is actually included in the link? If not, the link won't include the actual id, since the '=' is needed to not just access a variable but also display it.
<% artists.forEach(Artist=> { %>
<div><%= Artist.last_name %></div>
View
<% }) %>
Hope this helps, and feel free to correct me, as I'm also just starting to learn the basics.
Related
I already tried some possible solutions and even created and wrote the code again but I am still getting errors. I have created a diminute version of my whole code which connects to the database using Mongoose but after the Schema is created and I import the model in places-controllers my data that I write in POSTMAN goes directly to:
FYI: In this case I want POST request from createPlace to properly work.
Data entry: URL: http://localhost:5000/api/places/
{
"title": "Punta Arena Stfdsfdsfsdfop",
"description": "One stop Stop. Does not have tr12affic lights.",
"busrespect": "12ysdfdsfsfes",
"address": "Avenida Solunna",
"creator": "52peru soiflsdjf36"
}
OUTPUT:
{
"status": "error caught"
}
which is what I told the program to define if the try did not work.
IN app.js I have the following code:
const express= require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const placesRoutes = require("./routes/places-routes");
const HttpError = require ("./models/http-error");
const app = express();
app.use(bodyParser.json());
app.use('/api/places', placesRoutes);
app.use((req, res, next) => {
const error= new HttpError('Route not available. Try something different?', 404);
throw error;
});
app.use((error, req, res, next) =>{
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500)
res.json({message: error.message || "An unknown error occured! Sorry" });
});
url = '<mongo_url>'
mongoose.connect(url, {useNewUrlParser: true}).then(()=>{
console.log("Connected to database")
app.listen(5000);
}).catch(erro => {
console.log(erro)
});
In places-routes.js I have the following code:
const express = require('express');
const {check} = require('express-validator')
const placesControllers=require('../controllers/places-controllers');
const router = express.Router();
router.get('/:pid', placesControllers.getPlaceById );
router.get('/user/:uid',placesControllers.getPlacesByCreatorId );
router.post('/' ,[
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 }),
check('address')
.not()
.isEmpty()
],
placesControllers.createPlace);
router.patch('/:pid', [
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 })
] , placesControllers.updatePlace );
router.delete('/:pid', placesControllers.deletePlace);
module.exports=router;
In places-controllers.js I have the following code:
const HttpError = require('../models/http-error');
const { validationResult } = require('express-validator');
//const getCoordsForAddress= require('../util/location');
const BusStop = require('../models/place');
let INITIAL_DATA = [
{
id: "p1",
title: "Samoa Stop",
description: "My first bus stop in Lima",
//location: {
// lat: 40.1382,
// lng:-23.23
// },
address: "Av. La Molina interseccion con calle Samoa",
busrespect: "yes",
creator: "u1"
}
];
const getPlaceById = (req, res, next) => {
const placeId = req.params.pid // Accessing the p1 in pid URL scrapping {pid:'p1'}
const place= INITIAL_DATA.find(p => { //find method goes over each element in the array, the argument p represents the element where find loop is
return p.id ===placeId
});
if (!place) {
const error= new HttpError('No bus stop found for the provided ID.', 404);
throw error;
}
res.json({place: place});
};
const getPlacesByCreatorId = (req, res, next)=> {
const userId = req.params.uid;
const places = INITIAL_DATA.filter(p=>{ //filter to retrieve multiple places, not only the first one
return p.creator ===userId;
});
if (!places || places.length===0) {
return next(
new HttpError('Could not find bus stops for the provide user id', 404)
);
}
res.json({places});
};
const createPlace = async (req, res,next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
return next(new HttpError ('Invalid bus stop please check your data', 422));
}
//const { title, description, busrespect, address, creator } = req.body; //erased location for now.
/* let place = new BusStop({
title: req.body.title,
description: req.body.description,
busrespect: req.body.busrespect,
address : req.body.address,
creator: req.body.creator
})
awaitplace.save()
.then(response=>{
res.json({
message : "Employee added sucessfully!"
})
})
.catch(err=>{
res.json({
message : "An error has occured!"
})
})
} */
const { title, description, busrespect, address, creator } = req.body;
try {
await BusStop.create({
title:title,
description: description,
busrespect:busrespect,
address: address,
creator: creator
});
res.send({status: "ok"});
} catch(error) {
res.send({status:"error caught"});
}
};
const updatePlace = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
console.log(errors);
throw new HttpError ("Invalid inputs passed, please check your data ", 422);
};
const { title, description } = req.body;
const placeId = req.params.pid;
const updatedPlace = { ...INITIAL_DATA.find(p => p.id === placeId)};
const placeIndex = INITIAL_DATA.findIndex(p => p.id === placeId);
updatedPlace.title = title;
updatedPlace.description = description;
INITIAL_DATA[placeIndex] = updatedPlace;
res.status(200).json({place: updatedPlace});
};
const deletePlace = (req, res, next) => {
const placeId = req.params.pid;
if (!INITIAL_DATA.find(p=> p.id ===placesId))
throw new HttpError('Could not find a bus stop for that ID ')
INITIAL_DATA = INITIAL_DATA.filter(p=> p.id !== placeId)
res.status(200).json({message: 'Deleted Place'});
};
exports.getPlaceById= getPlaceById;
exports.getPlacesByCreatorId = getPlacesByCreatorId;
exports.createPlace = createPlace;
exports.updatePlace = updatePlace;
exports.deletePlace = deletePlace;
Inside models folder I have two files: http-error.js which has this code:
class HttpError extends Error {
constructor(message, errorCode) {
super (message);
this.code = errorCode;
}
}
module.exports = HttpError;
The other file inside is the schema which is place.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const placeSchema = new Schema({
title: {
type: String
},
description: {
type: String
},
address: {
type: String
},
busrespect: {
type: String
},
creator: {
type: String
}
},
)
const BusStop = mongoose.model('BusStop', placeSchema)
module.exports= BusStop
Summary: somewhere in the try catch part from createPlace something is going wrong since my data entry is always going to the error status I indicated in that part.
I am having a problem to convert the following Ejs to pug
in admin/edit-product.ejs
we can make changes with product already we have it
but But I want to transfer ejs to pug
any solutions
<form class="product-form" action="/admin/<% if (editing) { %>edit-product<% } else { %>add-product<% } %>" method="POST">
in admin.js controller
exports.getAddProduct = (req, res, next) => {
res.render('admin/edit-product', {
pageTitle: 'Add Product',
path: '/admin/add-product',
editing: false
});
};
exports.postAddProduct=(req, res, next) => {
const title=req.body.title;
const imageUrl=req.body.imageUrl;
const price=req.body.price;
const description=req.body.description;
const product=new Product(title,imageUrl,description,price);
product.save();
res.redirect('/');
};
exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/');
}
const prodId = req.params.productId;
Product.findById(prodId, product => {
if (!product) {
return res.redirect('/');
}
res.render('admin/edit-product', {
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
});
};
Pug supports inline JavaScript code, so you could use a ternary conditional within some attribute interpolation like this:
form.product-form(action='/admin/' + (editing ? 'edit' : 'add') + '-product', method='POST')
Or for a more readable approach, construct the action path beforehand in a code block and store it in a variable:
-
let action = editing ? 'edit' : 'add'
let actionPath = `/admin/${action}-product`
form.product-form(action= actionPath, method='POST')
In learning how to use Objection.js, I am interested in learning how to implement a join table and populate it with the associated foreign keys. I made some progress but I'm not sure I am setting things up correctly. I created a smaller side project from my main project that is simplified so I can test without all the extra noise from the code I do not need to troubleshoot. So far, I can set this ORM up fine with no errors. Now I am interested in utilizing join tables and turn to the StackOverflow Community for any feedback I may be given. Going through the documentation, I can see that I would need to make use of the 'extra' property inside my relationMappings() method.
I made sure to create the correct mapping for each model, Actors, Movies and ActorsMovies. I also made sure to create a model for the join table. When I first started testing, I added the 'extra' property to the migration of the 'actors_movies' table as a string, then changed the data type to integer because ultimately, that is how I intend on using it. In order for this to be implemented correctly, do I only need one 'extra' property? Because I added a second 'extra' property named 'author'. So, the two are now 'character' used in the Actor model and 'author' in the Movie model.
Additional pages from Objection that I referenced are the following:
Join Table Recipe and
Ternary relationships Recipe
My small test comes from the examples that were provided in the Objection documentation, so that will be the point of reference I will put here. Three tables: Actors, Movies and ActorsMovies.
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class Actor extends Model {
static get tableName() {
return 'actors'
}
static get relationMappings() {
const Movie = require('./Movie')
return {
movies: {
relation: Model.ManyToManyRelation,
modelClass: Movie,
join: {
from: 'actors.id',
through: {
from: 'actors_movies.actor_id',
to: 'actors_movies.movie_id',
extra: {
character: 'character'
}
},
to: 'movies.id'
}
}
};
}
}
module.exports = Actor;
//Movies.js
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class Movie extends Model {
static get tableName() {
return 'movies'
}
static get relationMappings() {
const Actor = require('./Actor')
return {
actors: {
relation: Model.ManyToManyRelation,
modelClass: Actor,
join: {
from: 'movies.id',
through: {
from: 'actors_movies.movie_id',
to: 'actors_movies.actor_id',
extra: {
author: 'author'
}
},
to: 'actors.id'
}
}
};
}
}
module.exports = Movie;
//ActorsMovies.js
const { Model } = require('objection');
const knex = require('../db/dbConfig');
Model.knex(knex);
class ActorsMovies extends Model {
static get tableName() {
return 'actors_movies';
}
static get idColumn() {
return ['actor_id', 'movie_id'];
}
static get relationMappings() {
const Actor = require('./Actor');
const Movie = require('./Movie');
return {
actor: {
relation: Model.BelongsToOneRelation,
modelClass: Actor,
join: {
from: 'actors_movies.actor_id',
to: 'actors.id'
}
},
movie: {
relation: Model.BelongsToOneRelation,
modelClass: Movie,
join: {
from: 'actors_movies.movie_id',
to: 'movies.id'
}
}
};
}
}
module.exports = ActorsMovies;
For this test project, I am interested in making sure the ActorsMovies table gets correctly populated with the actor_id and the movie_id when a movie is created with a POST request.
// api/actors.js
const express = require('express');
const router = express.Router();
const Actors = require('../models/Actor');
const Movies = require('../models/Movie');
/************************/
/********* READ *********/
/************************/
router.get('/', async (req, res, next) => {
try {
const user = await Actors.query();
res.status(200).json(user)
} catch(error) {
console.log(error.message)
}
});
router.get('/:id', async (req, res, next) => {
try {
const actorId = req.params.id;
const actor = await Actors.query().findById(actorId);
const movie = await Actors.relatedQuery('movies')
.for(actor.id)
.insert({ name: actor.name, character: actor.id }).debug()
res.status(200).json(movie)
} catch (error) {
console.log(error.message)
}
});
module.exports = router;
// api/movies.js
const express = require('express');
const router = express.Router();
const Movies = require('../models/Movie');
/************************/
/********* READ *********/
/************************/
router.get('/', async (req, res, next) => {
try {
const movie = await Movies.query();
res.status(200).json(movie)
} catch(error) {
console.log(error.message)
}
});
router.get('/:id', async (req, res, next) => {
try {
const movieId = req.params.id;
const movie = await Movies.query().findById(movieId);
const actor = await Movies.relatedQuery('actors')
.for(movie.id)
.insert({ name: 'The Room', author: movie.id }).debug();
res.status(200).json(actor)
} catch (error) {
console.log(error.message)
}
});
/************************/
/******** CREATE ********/
/************************/
router.post('/', async (req, res, next) => {
try {
const createMovie = req.body;
const newMovie = await Movies.query().insert(createMovie);
const actor = await Movies.relatedQuery('actors')
.for(newMovie.id)
.insert({ name: newMovie.name, author: newMovie.id })
res.status(201).json(actor)
} catch (error) {
console.log(error.message)
}
});
module.exports = router;
//migration file
exports.up = knex => {
return knex.schema
.createTable('actors', table => {
table.increments('id').primary();
table.string('name');
table.timestamps(false, true);
})
.createTable('movies', table => {
table.increments('id').primary();
table.string('name');
table.timestamps(false, true);
})
.createTable('actors_movies', table => {
table.integer('actor_id').references('actors.id');
table.integer('movie_id').references('movies.id');
// The actor's character's name in the movie.
table.integer('character');
table.integer('author');
table.timestamps(false, true);
});
};
exports.down = function(knex) {
return knex.schema
.dropTableIfExists('actors_movies')
.dropTableIfExists('movies')
.dropTableIfExists('actors')
};
// dbConfig.js
require('dotenv').config();
const environment = process.env.NODE_ENV || 'development'
const config = require('../knexfile.js')[environment]
module.exports = require('knex')(config)
The server works fine, the connection between knex.js and Objection.js is fine too. I get a clean response in Postman, but I'm hoping to get an experienced opinion on how I am implementing this. As a side note, I did scour StackOverflow and did not find my specific question, so your feedback will be greatly appreciated.
I recently created a simple MERN application that is supposed to use a form to send data to the backend using Redux to maintain state management. I'm new to Redux (as you will see in my code) and I believe I must have messed up the dispatching.
Below are the functions in my Form component:
const [landlordData, setLandlordData] = useState({name: '', type: '', rating: '', details: ''});
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
console.log(landlordData);
dispatch(createLandlord(landlordData));
}
Which console log the data from the form normally. When I submit though the new entry in the MongoDB only includes the time created and the UUID of the entry due to the Schema of the database:
import mongoose from 'mongoose';
const landlordSchema = mongoose.Schema({
name: String,
type: String,
rating: Number,
details: String,
createdAt: {
type: Date,
default: new Date()
}
});
var landlordDetails = mongoose.model('Landlords', landlordSchema);
export default landlordDetails;
To provide more context on the backend operations here is the controller script I made:
import landlordDetails from '../models/landlords.js';
export const getLandlords = async (req, res) => {
try {
const getDetails = await landlordDetails.find();
console.log(getDetails);
res.status(200).json(getDetails);
} catch (error) {
res.status(404).json({ message: error.message });
}
}
export const createLandlords = async (req, res) => {
const details = req.body;
const newLandlord = new landlordDetails(details);
try {
await newLandlord.save();
res.status(201).json(newLandlord);
console.log("New landlord added!");
} catch (error) {
res.status(409).json({ message: error.message })
}
}
Please let me know if any more information is needed or if I am completely oblivious to something obvious. Thank you.
EDIT: To provide more context, here are my api calls and my action script:
API:
import axios from 'axios';
const url = 'http://localhost:5000/landlords';
export const fetchLandlords = () => axios.get(url);
export const createLandlord = (landlordData) => axios.post(url, landlordData);
Actions JS file:
import * as api from '../api/index.js';
//Action creators
export const getLandlords = () => async (dispatch) => {
try {
const { data } = await api.fetchLandlords();
dispatch({ type: 'FETCH_ALL', payload: data });
} catch (error) {
console.log(error.message);
}
};
export const createLandlord = (landlord) => async (dispatch) => {
try {
const { data } = await api.createLandlord(landlord);
dispatch({ type: 'CREATE', payload: data });
} catch (error){
console.log(error);
}
};
When I click the submit button, a new database entry is made with the createdAt field but nothing else.
I'm trying to create a recipe search app using Express as my backend, and am getting the error message in the title from my Router file when I start my server up. I've made projects before where my Router follows the same as it does here, but for some reason I keep getting the error and I can't figure out why. Below I've pasted the code to my controller, helper, and route files:
Controller:
// import model and users controller
const Recipe = require('../models/recipe');
const usersController = require('../controllers/users-controller');
// initiate controller object
const recipesController = {}
// send API data
recipesController.sendApiRecipe = (req, res) => {
res.json({
message: `recipe returned`,
recipe: res.locals.recipe,
})
}
// show all favorited recipes
recipesController.index = (req, res, next) => {
Recipe.findByUser(req.user.id)
.then(recipe => {
res.json({
message: 'rendering favorites',
data: { recipe },
})
}).catch(next)
}
// create favorite recipe
recipesController.create = (req, res) => {
console.log(req.body, 'from create/recipesController')
Recipe.create({
title: req.body.title,
diet: req.body.diet,
calories: req.body.calories,
servings: req.body.servings,
health: req.body.health,
ingredient: req.body.ingredient,
img: req.body.img,
link: req.body.link,
user_id: req.user.id,
}).then(recipe => {
res.json({
message: 'successfully added',
data: { recipe }
})
}).catch(err => {
console.log(err)
res.status(500).json({error: err})
})
}
// delete favorite recipe
recipesController.delete = (req, res, next) => {
Recipe.destroy(req.params.id)
.then(() => {
res.json({
message: 'successfully deleted recipe',
})
}).catch(next)
}
export default recipesController;
Helper:
// import dependencies
require('isomorphic-fetch')
require('dotenv').config()
function getRecipes(req, res, next) {
// fetch URL
fetch(`https://api.edamam.com/search?q=${req.params.search}&app_id=${process.env.APP_ID}&app_key=${process.env.APP_KEY}&from=0&to=30`)
.then(res => res.json())
// use res.locals to attach data to repsonse object
.then(fetchRes => {
// set fetched results to res.locals
res.locals.recipe = fetchRes
next()
})
}
// export function
module.exports = {
getRecipes: getRecipes,
}
Routes:
// import dependencies
const express = require('express')
const recipeHelpers = require('../services/recipes/recipe-helpers')
const recipesController = require('../controllers/recipes-controller')
const recipesRouter = express.Router()
recipesRouter.get('/:search', recipeHelpers.getRecipes, recipesController.sendApiRecipe)
recipesRouter.post('/create', recipesController.create)
module.exports = recipesRouter;
Please let me know if there's any additional information I should provide, and I'll be certain to follow up with any findings I come across as I troubleshoot further. Thanks in advance for any help!
I just realized I didn't export my controller properly, and fixing that resolved the issue. Thanks!