Search code examples
node.jsexpressormnode-orm2

NPM ORM - Save update of hasOne Field


I have a setup where I have a person which has a certain role in my application.

I have following models

module.exports = function (orm, db) {
    var Person = db.define('person', {
        id:             { type: 'serial', key: true },
        name:           { type: 'text' },
        email:          { type: 'text' },
        password:       { type: 'text' },
        mobilenumber:   { type: 'text' },
        contract_id:    { type: 'integer' },
        role_id:        { type: 'integer' },
        status:         { type: 'integer' },
    });
  Person.hasOne('role', db.models.role, { autoFetch: true });
};

module.exports = function (orm, db) {
    var Role =  db.define('role', {
        id:             { type: 'serial', key: true },
        name:           { type: 'text' },
        description:    { type: 'text' },
    });
};

When creating a new person with a certain role everything works fine and the role is assigned.

create new user with role

template

extends layout

block content
  div.container

    div.row
      form(id='user_form' action='create' method='post')
        p name:
        input(type='text' name='name')
        p email:
        input(type='text' name='email')
        p password:
        input(type='password' name='password')
        p mobilenumber:
        input(type='text' name='mobilenumber')
        p role
        select(size='5' name='role')
          each role in roles
            option(value="#{role.id}") #{role}
        input(type='submit' value='add')

Controller

app.get('/new', function (req, res) {
  req.models.role.all(function (err, roles) {
    res.render('new', {roles:roles});
  });
});

app.post('/create', function (req, res) {
  var new_person = {};

  new_person.name = req.body.name;
  new_person.email = req.body.email;
  new_person.password = req.body.password;
  new_person.mobilenumber = req.body.mobilenumber;
  new_person.role_id = req.body.role;

  req.models.person.create(new_person, function (err, person) {
    if(err) throw err;
    res.redirect('/person');
  });
});

But when I try to update one entry every altered field gets updated except the role_id.

update existing user with role

template

extends layout

block content
  div.container

    div.row
      form(id='user_form' action='/person/update/#{person.id}' method='post')
        p name:
        input(type='text' name='name' value='#{person.name}')
        p email:
        input(type='text' name='email' value='#{person.email}')
        p password:
        input(type='password' name='password')
        p mobilenumber:
        input(type='text' name='mobilenumber' value='#{person.mobilenumber}')
        p role:
        select(size='5' name='role')
          each role in roles
            option(value="#{role.id}") #{role}
        input(type='submit' value='save')

controller

app.get('/edit/:id', function (req, res) {
  req.models.person.get(req.params.id, function (err, person) {
    req.models.role.all(function (err, roles) {
      res.render('edit', {person: person, roles: roles});
    });
  });
});

app.post('/update/:id', function (req, res) {

  req.models.person.get(req.params.id, function (err, person) {
    person.name = req.body.name;
    person.email = req.body.email;
    person.password = req.body.password;
    person.mobilenumber = req.body.mobilenumber;
    person.role_id = req.body.role;
    console.log(req.body.role); // even prints the correct id when updated

    person.save(function (err) {
      if(err) throw err;
      res.redirect('/person');
    });
  });

I even receive the correct role_id when updating the fields. Since saving the other attributes in the update works and the role_id is simply an attribute of person I don't understand, why this should not work out. If you need more code, please tell me. I am really stuck at the moment. Did anybody experience the same?

Edit: I even tried casting it to an int but that didn't change anything at all as well person.role_id = parseInt(req.body.role);


Solution

  • I had to use setRole in this case for the hasOne relation to save the entry.

    app.post('/update/:id', function (req, res) {
    
      req.models.person.get(req.params.id, function (err, person) {
        person.name = req.body.name;
        person.email = req.body.email;
        if (req.body.password) { person.password = req.body.password; }
        person.mobilenumber = req.body.mobilenumber;
    
        req.models.role.get(req.body.role, function (err, role) {
          if(err) throw err;
          person.setRole(role, function (err) {
    
            person.save(function (err) {
              if(err) throw err;
              res.redirect('/person');
            });
          });
        });
      });
    });