If you want to reduce clutter in your controllers you can use PathBindables to automatically convert URL parameters to your model objects or other custom objects. For example you can get rid of the code that takes an id, looks up the user in a database and checks for null etc by wrapping into a custom PathBindable implementation. This will also make it easier to reuse code among your controllers.
You will need to do 3 things to get this to work,
1. Create a controller and action, such aspublic static userName(User user) { return ok(user.getName()); }
Note that user is always non null and is safe to use. An exception is thrown internally if the lookup fails and Play will return a bad request response to the client.
2. Create a route, such asGET /user/:user MyController.userName(user : models.User)
Here we create an actual callable URL, for example, /user/124. In this example we use the id in the route but it can be anything that you can map to your model, for example unique email addresses.
3. Implement the PathBindable interfaceYou can add the PathBindable code to your existing model,
package models; import javax.persistence.Entity; import javax.persistence.Id; import play.Logger; import play.db.ebean.Model; import play.db.ebean.Model.Finder; import play.mvc.PathBindable; @Entity public class User extends Model implements PathBindableReferences, https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/java/play/mvc/PathBindable.java http://julien.richard-foy.fr/blog/2012/04/09/how-to-implement-a-custom-pathbindable-with-play-2/{ @Id Long id; String name; public String getName() { return name; } @Override public User bind(String key, String id) { // key is "user" // id is the ":user" part of the route, i.e. 1 if you have /user/1 User user = find.byId(new Long(id)); if (user == null) throw new IllegalArgumentException("User not found"); return user; } @Override public String javascriptUnbind() { return null; } @Override public String unbind(String arg0) { return name; } public static Finder find = new Finder (Long.class, User.class); }
Thanks for this useful article !
ReplyDeleteThe purpose of those methods is not perfectly straightforward ; I assume that "unbind" is used for reverse rooting.
If so, shouldn't it return the id instead of the name (to be bijective with "bind")?
Else the generated URL won't be bound correctly afterward.
Thanks !