Raja G
Raja G

Reputation: 6633

express get routes : how to achieve DRY

I have code like below to get process paths

router.get( "/todoHome", ( req, res ) => {
    res.render( "todoHome",
        { title: 'My Todo List!!' } );
} );

router.get( "/articles", ( req, res ) => {
    res.render( "articles",
        { title: 'Articles To Read' } );
} );

router.get( ["/", "/index"] ( req, res ) => {
    res.render( "index",
        { title: 'Homepage' } );
} );

router.get( "/primary" ( req, res ) => {
    res.render( "primaryurls",
        { title: 'Primary DC URLs' } );
} );

router.get( "/standby" ( req, res ) => {
    res.render( "standbyurls",
        { title: 'Standby DC URLs' } );
} );

I feel like I may add few more similar entries Is there any way I can implement DRY here ?

Thank you.

Upvotes: 0

Views: 149

Answers (4)

Raja G
Raja G

Reputation: 6633

I have found another similar solution as below

var titleObj = {
    "/kbs": "KB Articles",
    "/articles": "Articles-To-Read"
}

var renderObj = {
    "/kbs": "kbarticles",
    "/articles": "articles",
}

var schemaObj = {
    "/kbs": kbarticlesSchema,
    "/articles": kbarticlesSchema,
}

var routeArray = ["/kbs", "/articles"];

router.get( routeArray, ( req, res ) => {
    console.log( req.path );
    schemaObj[req.path].find()
        .then( ( kbs ) => {
            res.render( renderObj[req.path],
                {
                    title: titleObj[req.path],
                    kbs: kbs
                } );
        } );
} );

This way you dont have to touch router.get method, and you can keep updating new routes, by updating the respective objects as per your requirement.

Hope it helps.

Upvotes: 0

Syed Mishar Newaz
Syed Mishar Newaz

Reputation: 567

At best, you can chain those get calls.

router.get( "/todoHome", ( req, res ) => {
    res.render( "todoHome",
        { title: 'My Todo List!!' } );
})
.get( ["/", "/index"] ( req, res ) => {
    res.render( "index",
        { title: 'Homepage' } );
})
.get(
    //......
)

or

const titles = {
    'todoHome' : 'My Todo List',
    'index': 'Homepage',
    ......
}

router.get("*", ( req, res ) => {
    const path = req.path.replace('/', '')
    res.render( path, { title: titles[path] } );
})

Also, an advice: Don't try to be a code perfectionist. It will ruin your learning. Welcome to the real world. It's a bit dirty.

Upvotes: 1

jfriend00
jfriend00

Reputation: 707396

You can make the whole thing table-driven which is a goto technique when you have lots of similar looking data being used in repeated functions:

const routeData = [
    ['/todoHome', 'todoHome', 'My Todo List!!'],
    ['/articles', 'articles', 'Articles To Read'],
    ['/', 'index', 'Homepage'],
    ['/index', 'index', 'Homepage'],
    ['/primary', 'primaryurls', 'Primary DC URLs'],
    ['/standyby', 'standbyurls', 'Standby DC URLs']
];

// insert routes from the data in the table
for (const [path, name, title] of routeData) {
    app.get(path, (req, res) => {
        res.render(name, {title});
    });
}

Upvotes: 1

hoangdv
hoangdv

Reputation: 16137

You can create a helper function, the function will help you render your template.

Something like:

function renderPage(resObject, template, title = '', data = {}) {
  resObject.render(template, {
    title,
    ...data,
  });
}

then, use the function in the router functions:

router.get("/todoHome", (req, res) => {
  return renderPage(res, 'todoHome', 'My Todo List!!')
});

Upvotes: 0

Related Questions