I decided to use the Play Framework (version 2.2.x) for a school project, just to see how well it worked. I ran into an issue not long after starting; I wanted to test some of my models, and needed to have data in the database for this purpose.
The solution to this problem is usually fixtures (see https://docs.djangoproject.com/en/dev/howto/initial-data/ and http://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures), but I couldn’t find any up-to-date documentation on Play for this feature (there were plenty of documents for older versions, but that was useless to me).
After much Google-foo and keyboard bashing, I managed to get it working. For the sake of record, I’m going to record my findings here (perhaps it will save you time in your search).
Fixtures in Play
There is no official solution to this. However,play has support for YAML (through something called Snake YAML, http://code.google.com/p/snakeyaml/). Using YAML, and some basic functions in Java, you can quickly load up a database (don’t ask me how to export one, because I have no idea).
My solution to this was to create a file in my test.models package called “InitialData”, and provide static methods in here that would load data from the YAML files. Rather than give a long explanation about this file, just take a look and deduce your information (assume the following Schema: Books -< Chapters -< Paragraphs -< Sentences)
<preclass="prettyprint">package models;
import java.util.List;
import java.util.Map;
import play.libs.Yaml;
import com.avaje.ebean.Ebean;
public class InitialData {
public static void BasicData1() {
@SuppressWarnings("unchecked")
Map<String, List<Object>> all = (Map<String, List<Object>>) Yaml
.load("initial-data.yml");
// Insert books first
Ebean.save(all.get("books"));
Ebean.save(all.get("chapters"));
// Insert paragraphs
Ebean.save(all.get("paragraphs"));
// Insert sentences
Ebean.save(all.get("sentences"));
}
public static void UserData() {
// And user data
@SuppressWarnings("unchecked")
List<Object> all = (List<Object>) Yaml.load("initial-user-data.yml");
Ebean.save(all);
}
}</preclass="prettyprint">
The corresponding YAML files must be created in conf/, as that is where your application “root” is when being run from the Play terminal.
books:
- &balaclava !!models.Book
title: The Cause of the Charge of Balaclava
author: Thomas Morley
publicationDate: 2014-04-02
chapters:
- &chapter1 !!models.Chapter
book: *balaclava
paragraphs:
- ¶graph1 !!models.Paragraph
chapter: *chapter1
- ¶graph2 !!models.Paragraph
chapter: *chapter1
sentences:
- &sentence1 !!models.Sentence
paragraph: *paragraph1
content: There is a natural instinct to dodge cannon balls.
- &sentence2 !!models.Sentence
paragraph: *paragraph1
content: In such fire as we were under it changed to an impulse to hurry.
- &sentence3 !!models.Sentence
paragraph: *paragraph1
content: There was no time to look right or left, and the guns in front were what I looked out for.
- &sentence4 !!models.Sentence
paragraph: *paragraph1
content: They were visible as streaks of fire about two feet long, and a foot thick in the centre of a gush of thick white smoke, marking about every three hundred yards of the way, as they would reload in 30 or 40 seconds.
- &sentence5 !!models.Sentence
paragraph: *paragraph1
content: The last volley went off when we were close on them.
- !!models.Sentence
paragraph: *paragraph2
content: Before we reached the guns every officer of my squadron, the second, was either killed or wounded, leaving no one to command us.
YAML Syntax, abridged
The syntax of YAML isn’t too hard, and below I give a few “relevant” notes when using it to create fixtures for Play
- Indentation marks blocks
- You can “name” an entry by putting a &name in the declaration; you can later refer to it by using *name
- Note! You can NOT refer to something that hasn’t been declared yet. This creates a problem with M-M or 1-M relationships; just omit the relation in the first declaration. Play will figure it out when it encounters the second model
- To say that a declaration belongs to a model, add a !!
to the declaration (you can see this in the example above) - You can “group” declarations by putting a
: then indenting all the declarations in that group
If you’d like to see this in action, please take a look at the project I used it for (https://github.com/chuck211991/cfg)
Best of luck to you! Comment if you have issues, I’ll help if I can.