Models in node.js and data validation

 Development, node.js  Comments Off on Models in node.js and data validation
Nov 292011
 

So I have been learning about node.js and I have to say that so far I am finding myself warming to it.

I wanted to write a little bit about how I’ve enjoyed using models in a node.js app using the Express web framework.

I am using mongodb for this app and so I am using the mongoose data layer. Mongoose is described as a object modeling tool.

You define a model as follows:


var mongoose = require('mongoose')
, Schema = mongoose.Schema;

/event model/

var Event = new Schema({
title : {type: String, index: true}
, content : {type: String}
, startdate : Date
, enddate : Date
, creator : Schema.ObjectId
, longlat : {lon:Number,lat:Number}
, county : {type:String, index:true}

});

edit
Since writing this piece I have found out that there is a better way of achieving the same result. You can add validators to mongoosejs Schemas as follows:

Schema.path("link").validate(function(value){
if(value.search(/http:\/\/[a-z0-9\-\.]+\.[a-z][a-z][a-z\.]*/gi) !== -1){
return true;
}
return false;
}, "link error");


The path is the path to the field in the schema and the second arg is the type of error which will be thrown.


What I have really liked is the “middleware” options. So you can define methods which will be called at a certain point in the execution; for example pre save.
Here is an example:

Event.pre('save',function(next){

var errors = [];
console.log("I was called first before save");
if(this.title.length < 20) errors[errors.length] = {field:"title",message:"title invalid"}; if(errors.length > 0){
var error = new Error("Invalid Input");
error.errors = errors;
next(error);
}
next();

});

So in the above code next is the next function to be called in the chain which ends with the call back defined after save was called on the model

/some controller method

saveEvent : function(req,res){
var event = new Event();
event.title = req.body.title;
event.save(function(err,suc){
//control is returned here
if(err){ //do something with errors}
else{//succeeded}
});
}

You can define more than one function in your model to be called pre some event in this case the next will refer to the next peice of middleware.

For more info on mongoose you can see here Middle ware in mongoose

Models and Decorators adjusting data the right way

 Development, general  Comments Off on Models and Decorators adjusting data the right way
Nov 102011
 

Carrying on from my previous article about heavy lifting models Heavy lifting models I thought I would write a little about decorators and models.

What is a decorator
Briefly a decorator is an class whose purpose it is to decorate another object adding functionality or adjusting the current functionality. This can sometimes be a good alternative to subclassing.

A quick example

abstract class PricingDecorator implements Pricing {

Pricing price;

public PricingDecorator(Pricing price) {
this.price = price;
}
}

public class DiscountPricingDecorator extends PricingDecorator {

Discount discount;

public DiscountPricingDecorator(Pricing price, Discount discount) {
super(price);
this.discount = discount;
}

@Override
public Float getPrice() {
if (discount.getType() == Discount.DISCOUNT_TYPE_PERCENTAGE) {
return price.getPrice() - (discount.getValue() / 100) * price.getPrice();
} else if (discount.getType() == Discount.DISCOUNT_TYPE_PRICE) {
return discount.getValue();
}
return price.getPrice();
}
}

public class DiscountImp implements Discount {

public int type;
public Float value;

public DiscountImp(int type, Float value) throws InvalidDiscountType {
this.checkType(type);
this.type = type;
this.value = value;
}

@Override
public int getType() {
return type;
}

private void checkType(int type) throws InvalidDiscountType {
if (type == Discount.DISCOUNT_TYPE_PERCENTAGE || type == Discount.DISCOUNT_TYPE_PRICE) {
return;
} else {
throw new InvalidDiscountType("invalid discount type");
}
}

@Override
public void setType(int type) throws InvalidDiscountType {
this.checkType(type);
this.type = type;
}

@Override
public Float getValue() {
return value;
}

@Override
public void setValue(Float value) {
this.value = value;
}

}

So some of the above code is contrived and compacted to save too much code. The above would be used to decorate a Pricing Object with a various Discounts. As shown below:


try{
Discount discount = new DiscountImp(Discount.DISCOUNT_TYPE_PERCENTAGE, new Float(10));
Pricing price = new DiscountPricingDecorator(new ProductPricing(new Float(30)), discount);
System.out.print("discounted price" + price.getPrice());
}catch(InvalidDiscountType e){
e.printStackTrace();
}

It may be tempting to subclass your Pricing Object maybe into a DiscountedPricing:
and this is also an ok solution but in scenarios as seen above, I believe a Decorator is a better way of achieving this solution as I think it is clearer what is happening but because we have stuck to interface driven design we can reuse the decorator with other Pricing implementations and Discount implementations. It also maintains the simplicity of your Pricing Model class.

 

So recently I was asked for my thoughts on model view controller MVC and where business logic should be done. While I hope I answered the question well enough, I wanted to expand on my thoughts and maybe see what others thought.

What should a model know?
Often you see models represented as bare bean or container classes filled only with properties and setters and getters. Normally these properties relate to fields in some form of database. So the model only knows about the data it contains. This is a good thing. However it is also a very powerful piece of information. In my opinion the model should have many helper methods on top of the normal setters and getters to formulate the data as cleanly as possible for a nice skinny view and controller and also allowing improved decoupling of the code. The model should never contain any html, but an example of a helper method in a java bean model might be something like:

class Person{
private String firstName;
private String secondName;

/..Setter and Getters../

//helpers
public String getFullName(){
return firstName+" "+secondName;
}
}

Another example of a helper method but with a bit more meat to it:

class Customer implements CustomerModel {
private List<ProductModel> customerProducts;

//normally would be a Hibernate hasMany mapping
public List<ProductModel> getCustomerProducts(){
if(customerProducts == null){
Mapper mapper = new ProductMapper();
customerProducts = mapper.findById(this.customerId);
}
return customerProducts;
}

public Integer productCount(){
return getCustomerProducts().size();
}

Public Integer getCustomersTotalSpend(){
List<Products> prods = getCustomerProducts();
Integer total = 0;
if(prods.isEmpty()){
return total;
}
for(ProductModel prod : prods){
total+= prod.getValue();
}
return total;
}

}

These kind of methods are clearly tightly associated with the models data and so should never be done in the controller and even less so in the view. While the examples are a little simple and contrived, I think they highlight how you should think about your models. Having the model do as much as it can, but without stepping beyond the mark of what a model should know, provides you with the opportunity to have “Skinny controllers and Views with Fat Models”. In the above example, as long as you observe programming to an interface, you can easily swap in out models if needed without needing to change the controllers or the views and although I have written this example with Java in mind it transposes languages and is just as relevant in PHP or any other kind of language.

© 2012 Craig Brookes Suffusion theme by Sayontan Sinha