play手把手教你创建一个博客项目06增加特征tagging支持Word文档格式.docx
《play手把手教你创建一个博客项目06增加特征tagging支持Word文档格式.docx》由会员分享,可在线阅读,更多相关《play手把手教你创建一个博客项目06增加特征tagging支持Word文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
publicintcompareTo(TagotherTag){
returnpareTo(otherTag.name);
}
由于我们打算用findOrCreateByName(Stringname)工厂方法来实现懒散式特征创建或得到这些特征。
那么,让我们把它添加到Tag类里:
publicstaticTagfindOrCreateByName(Stringname){
Tagtag=Tag.find("
byName"
name).first();
if(tag==null){
tag=newTag(name);
returntag;
Taggingposts
是时候创建Tag模型与Post模型的关系了,让我们在Post类里创建正确的关系:
…
@ManyToMany(cascade=CascadeType.PERSIST)
publicSet<
tags;
publicPost(Userauthor,Stringtitle,Stringcontent){
ments=newArrayList<
Comment>
();
this.tags=newTreeSet<
this.author=author;
this.title=title;
this.content=content;
this.postedAt=newDate();
请注意,在这里我们使用了TreeSet以可预知的顺序来保存特征列表(事实上是按字母顺序的,这是基于我们之前compareTo实现)。
在这里,我们仅使用单向关系。
同时,我们将添加很多帮助方法来使特征管理简单化,第一个用于tag一个Post:
publicPosttagItWith(Stringname){
tags.add(Tag.findOrCreateByName(name));
returnthis;
下一个用于通过指定的tag找回所有的博文:
publicstaticList<
Post>
findTaggedWith(Stringtag){
returnPost.find(
"
selectdistinctpfromPostpjoinp.tagsastwheret.name=?
"
tag
).fetch();
是时候测试这些新代码了,让我们重新启动服务器到测试模式:
$playtest
在basicTest类里添加@Test:
@Test
publicvoidtestTags(){
//Createanewuserandsaveit
Userbob=newUser("
bob@"
"
secret"
Bob"
).save();
//Createanewpost
PostbobPost=newPost(bob,"
Myfirstpost"
Helloworld"
PostanotherBobPost=newPost(bob,"
Hop"
//Well
assertEquals(0,Post.findTaggedWith("
Red"
).size());
//Tagitnow
bobPost.tagItWith("
).tagItWith("
Blue"
anotherBobPost.tagItWith("
Green"
//Check
assertEquals(2,Post.findTaggedWith("
assertEquals(1,Post.findTaggedWith("
检查其是否正常工作。
下面的内容比上面的要难一点
好了,如果打算用多个tag来找回博文又该怎么做?
看起来,这样难一点!
下面我将给你一些非常有用的JPQL查询,这些查询可能对你的web项目有用:
findTaggedWith(String...tags){
selectdistinctpfromPostpjoinp.tagsastwheret.namein(:
tags)groupbyp.id,p.author,p.title,p.content,p.postedAthavingcount(t.id)=:
size"
).bind("
tags"
tags).bind("
tags.length).fetch();
最棘手的部分就是我们必须使用havingcount语句来对联合查询视图进行过滤,仅让完全拥有全部tag的博文通过。
请注意,在这里我们不能使用Post.find("
…"
tags,tags.count)签名进行查询。
这是因为tags已经是变量参数(vararg)了。
测试程序如下:
assertEquals(1,Post.findTaggedWith("
assertEquals(0,Post.findTaggedWith("
特征(tag)云
哪里有tags,哪里就需要一个tag云。
让我们在Tag类里添加一个方法来生成tag云:
Map>
getCloud(){
List<
result=Tag.find(
selectnewmap(t.nameastag,count(p.id)aspound)fromPostpjoinp.tagsastgroupbyt.nameorderbyt.name"
returnresult;
在这里,我们使用了hibernate的一个现成特性,这个特性允许我们从一个JPA查询里返回一个定制对象。
这个在List里的结果包含了一个Map,Map中的每个tag都带有两个key:
tag用作tag名称,pound用作tag统计结果。
测试代码为:
List<
cloud=Tag.getCloud();
assertEquals(
[{tag=Blue,pound=1},{tag=Green,pound=1},{tag=Red,pound=2}]"
cloud.toString()
);
为博客UI添加tags(特征)
现在,我们就可以用新的特征填充物来为浏览博客增加一个新的途径。
和以前一样,为了高效工作,我们需要在最初的数据集里添加许多tags。
修改/yabe/conf/initial-data.yml文件,添加一些tags用于测试:
Tag(play):
name:
Play
Tag(architecture):
Architecture
Tag(test):
Test
Tag(mvc):
MVC
把这些tag添加到post的数据描述里:
Post(jeffPost):
title:
TheMVCapplication
postedAt:
2009-06-06
author:
jeff
tags:
-play
-architecture
-mvc
content:
>
APlay
注意:
一定要把这些Tags数据描述添加到YAML文件头部,这是因为这些数据需要在任何Post引用它们时进行创建。
现在重新启动应用程序,强制加载这些新的数据集。
请注意,play甚至会告诉你在YAML文件里存在的问题:
然后修改#{display/}标签来显示这些tag集(在full博文视图下)。
修改/yabe/app/views/tags/display.html文件:
#{if_as!
='
full'
<
spanclass="
post-comments"
>
&
nbsp;
|&
${_ments.size()?
:
'
no'
comment${_ments.size().pluralize()}
#{if_ments}
latestby${_ments[0].author}
#{/if}
/span>
#{/if}
#{elseif_post.tags}
post-tags"
-Tagged
#{listitems:
_post.tags,as:
'
tag'
ahref="
#"
${tag}<
/a>
${tag_isLast?
:
'
#{/list}
#{/elseif}
创建‘特征相关(taggedwith)’页面
现在,我们就可以通过tags(特征)来列出发表的博文。
在上面的#{display/}标签里,我们把链接暂时留为空链接(用#),下面我们将通过一个链接到新创建的listTaggedaction替换他们:
-Tagged
#{listitems:
@{Application.listTagged(tag.name)}"