Giter Site home page Giter Site logo

Model Validation about bookshelf HOT 15 CLOSED

bookshelf avatar bookshelf commented on April 28, 2024
Model Validation

from bookshelf.

Comments (15)

calmdev avatar calmdev commented on April 28, 2024 1

I believe this is exactly what I needed. Can you verify if the implementation is ok? I want to share it incase others are interested in this. Your example above demonstrates use for more complex cases, I think - which is pretty cool.

Model:

var User = Bookshelf.Model.extend({
    tableName: 'users',
    initialize: function() {
        this.on('saving', this.validate, this);
    },
    validations: {
        email: ['required', 'validEmail'],
        username: ['required', 'alphaNumeric'],
        age: ['isNumeric']
    },
    validate: function(model, attrs, options) {
        return CheckIt(this.toJSON()).run(this.validations);
    }
});

Usage:

User.forge({
    email: 'invalid@testcom',
    username: 'joe-invalid'
}).save().then(function(user) {
    console.log(user.toJSON());
}, function(errors) {
    console.log(errors.toJSON());
    // { email: 'The email must contain a valid email address', username: 'The username must only contain alpha-numeric characters' }
});

from bookshelf.

tgriesser avatar tgriesser commented on April 28, 2024

Hey @calmdev - So I'm actually writing a separate library for validation... https://github.com/tgriesser/checkit

I'll advertise/give examples for it a bit more once I polish things up - the docs and test suite are still a little bare, but in my own projects it's been working great so-far... I've been using it alongside Bookshelf and it works well (especially with the use of promises)... Feel free to check it out and see how you like it (and open any tickets/pull requests if things aren't working as you'd expect).

My reasoning here is that (in my experience) you'll very often want to validate models differently based on access control, special cases, etc... so I figured it'd be better to separate this out and provide hooks for than to try getting validators all tangled up with the relation logic.

from bookshelf.

tgriesser avatar tgriesser commented on April 28, 2024

I actually may provide a bare bones integration for it once it's done. But here's a very brief example use in a model:

initialize: function() {
   this.on('saving', this.validate, this);
},

validations: {
  user: {
      email: ['required', 'validEmail'],
      password: ['required']
  },
  admin: {
      email: ['required', 'validEmail'],
  }
}

validate: function(model, attrs, options) {
   options.role || (options.role = 'user') {
     return CheckIt(this.toJSON()).run(this.validations[options.role]);
   }
}

Then saving...

model.save({email: '[email protected]'}, {role: req.user.acl});

from bookshelf.

calmdev avatar calmdev commented on April 28, 2024

Ok, well that makes sense to me - I agree with the reasoning. I wanted to ask that way I don't do anything that goes against the progression of this project as I want to continue using it - very promising. I am going to check out the work that you have started with the checkit library.

Thanks for the example.

I was going to ask about it, but then it suddenly appeared as I was typing this reply. I will try it out!

from bookshelf.

tgriesser avatar tgriesser commented on April 28, 2024

Yeah, that looks good - the only thing that might be an issue there is if you get an error that isn't a CheckIt error but is for some reason another error (database or whatever)... then you likely won't have a toJSON method... so what I've been doing so far is a instanceof check to determine whether to call toJSON on the error object.

Here's an example with express:

var errorHandler = function(res) {
   return function(error) {
      if (error instanceof CheckIt.Error) {
        res.json(400, {error: error.toJSON()});
      } else {
        res.json(400, {error: error.message});
      }
   };
};

// Elsewhere ...
.save().then(function(user) {
    console.log(user.toJSON());
}).catch(errorHandler(res));

from bookshelf.

calmdev avatar calmdev commented on April 28, 2024

Excellent. Thanks for the tip.

from bookshelf.

ErisDS avatar ErisDS commented on April 28, 2024

Just an idea, but it would be cool to provide an example using node-validator

from bookshelf.

pon avatar pon commented on April 28, 2024

We've tried implementing this pattern using Bookshelf and CheckIt. Everything behaves as expected, except we are seeing a "Possibly unhandled TypeError: Invalid validation" error logged. We are handling the error in the forge promise, but it is still being logged. I'm curious if this is expected behavior or something that other people have run in to.

from bookshelf.

tgriesser avatar tgriesser commented on April 28, 2024

@PeteOtto can you show the code you're running into that with? You shouldn't get any possibly unhandled errors if all goes well.

from bookshelf.

pon avatar pon commented on April 28, 2024

https://gist.github.com/peteotto/9415651

from bookshelf.

tgriesser avatar tgriesser commented on April 28, 2024

I've updated my comment above... It's generally an anti-pattern to do .then(onSuccess, onError) because if an error is thrown in the onSuccess it's not handled.

Your code example would be better written as:

create = {
  handler: function(request, reply) {
    return new Address().save({
      name: request.payload.name,
      address_line1: request.payload.address_line1
    }).then(function(model) {
      return new Address({
        'id': model.id
      }).fetch();
    }).then(function(model) {
      return reply(model);
    }).catch(function(error) {
      return reply(error);
    });
  }
};

from bookshelf.

pon avatar pon commented on April 28, 2024

Thanks Tim - I'll give that a try!

from bookshelf.

bendrucker avatar bendrucker commented on April 28, 2024

@PeteOtto The create handler can be cut down a whole lot:

create = {
  handler: function(request, reply) {
    return new Address().save({
      name: request.payload.name,
      address_line1: request.payload.address_line1
    })
    .call('fetch')
    .then(reply)
    .catch(reply);
  }
};

from bookshelf.

thetutlage avatar thetutlage commented on April 28, 2024

It is mandatory to use checkit , i want to use https://www.npmjs.org/package/indicative , but for some reason it does not work

from bookshelf.

bendrucker avatar bendrucker commented on April 28, 2024

Not at all @thetutlage. Please open a new issue though if you're having trouble.

from bookshelf.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.