Fixtures
Playではエンティティの初期データ作成のために Fixtures という仕組みが提供されている。Rails と同様。test/data.yml に以下の YAML ファイルを用意。
# Test data
User(bob):
email: bob@gmail.com
password: secret
fullname: Bob
isAdmin: true
User(jeff):
email: jeff@gmail.com
password: secret
fullname: Jeff
Post(firstBobPost):
title: About the model layer
postedAt: 2009-06-14
author: bob
content: >
The model has a central position in a Play! application. It is the domain-specific
representation of the information on which the application operates.
Martin fowler defines it as :
Responsible for representing concepts of the business, information about the
business situation, and business rules. State that reflects the business situation
is controlled and used here, even though the technical details of storing it are
delegated to the infrastructure. This layer is the heart of business software.
Post(secondBobPost):
title: Just a test of YABE
postedAt: 2009-03-25
author: bob
content: >
Well, it's just a test.
Post(jeffPost):
title: The MVC application
postedAt: 2009-06-06
author: jeff
content: >
A Play! application follows the MVC architectural pattern as applied to the
architecture of the Web.
This pattern splits the application into separate layers: the Presentation
layer and the Model layer. The Presentation layer is further split into a
View and a Controller layer.
Comment(c1):
author: Guest
content: >
You are right !
postedAt: 2009-06-14
post: firstBobPost
Comment(c2):
author: Mike
content: >
I knew that ...
postedAt: 2009-06-15
post: firstBobPost
Comment(c3):
author: Tom
content: >
This post is useless ?
postedAt: 2009-04-05
post: secondBobPost
Fixtures の利用
Fixtures は以下で YAML からエンティテイの情報を読み込み永続化できる。
Fixtures.load("data.yml");
/test/BasicTest.javaに以下のテストメソッド追加。
@Test public void fullTest() { Fixtures.load("data.yml"); // Count things assertEquals(2, User.count()); assertEquals(3, Post.count()); assertEquals(3, Comment.count()); // Try to connect as users assertNotNull(User.connect("bob@gmail.com", "secret")); assertNotNull(User.connect("jeff@gmail.com", "secret")); assertNull(User.connect("jeff@gmail.com", "badpassword")); assertNull(User.connect("tom@gmail.com", "secret")); // Find all bob's posts List<Post> bobPosts = Post.find("author.email", "bob@gmail.com").fetch(); assertEquals(2, bobPosts.size()); // Find all comments related to bob's posts List<Comment> bobComments = Comment.find("post.author.email", "bob@gmail.com").fetch(); assertEquals(3, bobComments.size()); // Find the most recent post Post frontPost = Post.find("order by postedAt desc").first(); assertNotNull(frontPost); assertEquals("About the model layer", frontPost.title); // Check that this post has two comments assertEquals(2, frontPost.comments.size()); // Post a new comment frontPost.addComment("Jim", "Hello guys"); assertEquals(3, frontPost.comments.size()); assertEquals(4, Comment.count()); }
起動時の初期データ
Fixtures は起動時の初期データ投入にも利用できる。
/app/Bootstrap.java に以下を作成。
import play.*; import play.jobs.*; import play.test.*; import models.*; @OnApplicationStart public class Bootstrap extends Job { public void doJob() { // Check if the database is empty if(User.count() == 0) { Fixtures.load("initial-data.yml"); } } }
Play の Job は HTTP リクエストとは別に特定の条件で起動するcron jobとして利用できる。上記は @OnApplicationStart アノテーションによりアプリケーションのスタート時に自動実行される。
Playの起動モードは DEV と PROD モードがあり、DEVモード時には初回のHTTPアクセス時にデータ作成が行われる。PROD モードの場合にはアプリケーションの起動時となる。DEV モードではアクセス時のブラウザ画面にてエラーの原因を表示するため。
テストデータ用のYAMLは/conf/initial-data.yml に、前述のdata.yml の内容で作成。
トップページの作成
/app/controllers/Application.java を変更してトップページのコントローラを作成。
public class Application extends Controller { public static void index() { Post frontPost = Post.find("order by postedAt desc").first(); List<Post> olderPosts = Post.find( "order by postedAt desc" ).from(1).fetch(10); render(frontPost, olderPosts); } }
render の引数として取得した情報を渡している。
これらの情報を表示するページテンプレートを編集 /app/views/Application/index.html
#{extends 'main.html' /}
#{set title:'Home' /}
#{if frontPost}
<div class="post">
<h2 class="post-title">
<a href="#">${frontPost.title}</a>
</h2>
<div class="post-metadata">
<span class="post-author">by ${frontPost.author.fullname}</span>
<span class="post-date">${frontPost.postedAt.format('MMM dd')}</span>
<span class="post-comments">
|
${frontPost.comments.size() ?: 'no'}
comment${frontPost.comments.size().pluralize()}</a>
#{if frontPost.comments}
, latest by ${frontPost.comments[0].author}
#{/if}
</span>
</div>
<div class="post-content">
${frontPost.content.nl2br()}
</div>
</div>
#{if olderPosts.size() > 1}
<div class="older-posts">
<h3>Older posts <span class="from">from this blog</span></h3>
#{list items:olderPosts, as:'oldPost'}
<div class="post">
<h2 class="post-title">
<a href="#">${oldPost.title}</a>
</h2>
<div class="post-metadata">
<span class="post-author">
by ${oldPost.author.fullname}
</span>
<span class="post-date">
${oldPost.postedAt.format('dd MMM yy')}
</span>
<div class="post-comments">
${oldPost.comments.size() ?: 'no'}
comment${oldPost.comments.size().pluralize()}
#{if oldPost.comments}
- latest by ${oldPost.comments[0].author}
#{/if}
</div>
</div>
</div>
#{/list}
</div>
#{/if}
#{/if}
#{else}
<div class="empty">
There is currently nothing to read here.
</div>
#{/else}
Fixtures にて設定したデータが表示されていることが分る。

