摘要:對添加標簽的支持隨著博客的文章越來越多,找到要找的文章越來越難。如果能夠添加標簽,那就能更好地分類文章了。要在模式下啟動應用,輸入添加新的到類確保它能工作。為了保持高效,我們需要向初始數據集添加標簽測試數據。修改來添加一些標簽數據。
對添加標簽的支持
隨著博客的文章越來越多,找到要找的文章越來越難。如果能夠添加標簽,那就能更好地分類文章了。
Tag模型我們將給博客的模型們添加新成員。對Tag類的定義是非常簡單的:
package models; import java.util.*; import javax.persistence.*; import play.db.jpa.*; @Entity public class Tag extends Model implements Comparable{ public String name; private Tag(String name) { this.name = name; } public String toString() { return name; } public int compareTo(Tag otherTag) { return name.compareTo(otherTag.name); } }
因為有時想要在需要時才創建標簽,我們寫多一個findOrCreateByName(String name)工廠方法。把它加到Tag類:
public static Tag findOrCreateByName(String name) { Tag tag = Tag.find("byName", name).first(); if(tag == null) { tag = new Tag(name); } return tag; }給文章打標簽
現在是時候連接Tag和Post模型。讓我們給Post類添加相應的關系:
… @ManyToMany(cascade=CascadeType.PERSIST) public Settags; public Post(User author, String title, String content) { this.comments = new ArrayList (); this.tags = new TreeSet (); this.author = author; this.title = title; this.content = content; this.postedAt = new Date(); } …
注意我們這里使用TreeSet來保持一個有序的標簽列表。(由于我們之前的compareTo實現,按的是字母順序)
我們將保持該關系為單向關系。
我們將給Post類添加一系列輔助函數。第一個用于給Post打標簽:
… public Post tagItWith(String name) { tags.add(Tag.findOrCreateByName(name)); return this; } …
下一個是根據指定標簽查找所有文章:
… public static ListfindTaggedWith(String tag) { return Post.find( "select distinct p from Post p join p.tags as t where t.name = ?", tag ).fetch(); } …
是時候寫一個新的測試用例了。要在test模式下啟動應用,輸入:
$ play test
添加新的@Test到BasicTest類:
@Test public void testTags() { // Create a new user and save it User bob = new User("bob@gmail.com", "secret", "Bob").save(); // Create a new post Post bobPost = new Post(bob, "My first post", "Hello world").save(); Post anotherBobPost = new Post(bob, "Hop", "Hello world").save(); // Well assertEquals(0, Post.findTaggedWith("Red").size()); // Tag it now bobPost.tagItWith("Red").tagItWith("Blue").save(); anotherBobPost.tagItWith("Red").tagItWith("Green").save(); // Check assertEquals(2, Post.findTaggedWith("Red").size()); assertEquals(1, Post.findTaggedWith("Blue").size()); assertEquals(1, Post.findTaggedWith("Green").size()); }
確保它能工作。
解決難題如果你想要根據多個標簽來查找相應的文章,該怎么辦?這個問題比表面看上去要難。
我將直接給你所需的JPQL查詢語句:
… public static ListfindTaggedWith(String... tags) { return Post.find( "select distinct p from Post p join p.tags as t where t.name in (:tags) group by p.id, p.author, p.title, p.content,p.postedAt having count(t.id) = :size" ).bind("tags", tags).bind("size", tags.length).fetch(); } …
代碼的關鍵在于,我們需要使用一個having count語句來從連結產生的視圖中過濾出擁有全部標簽的文章。
注意這里我們不能用Post.find("...", tags, tags.count)語法,因為tags是一個變長參數。
你可以在前一個測試中加入更多的檢查來測試它:
… assertEquals(1, Post.findTaggedWith("Red", "Blue").size()); assertEquals(1, Post.findTaggedWith("Red", "Green").size()); assertEquals(0, Post.findTaggedWith("Red", "Green", "Blue").size()); assertEquals(0, Post.findTaggedWith("Green", "Blue").size()); …標簽集合
我們最好有一個標簽集合來看看有哪些標簽。讓我們給Tag類添加一個方法來生成標簽集合:
public static List
這里,我們使用Hibernate的一個允許我們從JPA查詢中返回自定義對象的特性。返回的結果是一個Map列表,其中每個Map包括標簽名(鍵)和標簽個數(值)。
在我們前面的測試中加多一個檢查:
… List向博客界面添加標簽cloud = Tag.getCloud(); assertEquals( "[{tag=Blue, pound=1}, {tag=Green, pound=1}, {tag=Red, pound=2}]", cloud.toString() );
現在我們又多了一個瀏覽文章的方式了。為了保持高效,我們需要向初始數據集添加標簽測試數據。
修改/yabe/conf/initial-data.yml來添加一些標簽數據。比如:
… Tag(play): name: Play Tag(architecture): name: Architecture Tag(test): name: Test Tag(mvc): name: MVC …
然后添加它們到文章的聲明中:
… Post(jeffPost): title: The MVC application postedAt: 2009-06-06 author: jeff tags: - play - architecture - mvc content: > A Play …
在YAML文件的頂部添加Tags的定義,因為它們會被Post用到。
你需要重啟應用來加載新的初始數據。注意Play甚至會告訴你出現在YAML文件中的問題:
然后修改#{display /}標簽,在全文模式下展示標簽集合。修改/yabe/app/views/tags/display.html:
… #{if _as != "full"} | ${_post.comments.size() ?: "no"} comment${_post.comments.size().pluralize()} #{if _post.comments} , latest by ${_post.comments[0].author} #{/if} #{/if} #{elseif _post.tags} - Tagged #{list items:_post.tags, as:"tag"} ${tag}${tag_isLast ? "" : ", "} #{/list} #{/elseif} …標簽頁面
現在我們可以實現通過標簽瀏覽文章了。在#{display /}標簽,之前,我們留下一個空鏈接;現在終于可以用listTagged action補完它(修改yabe/app/views/tags/display.html):
… - Tagged #{list items:post.tags, as:"tag"} ${tag}${tag_isLast ? "" : ", "} #{/list} …
在Application控制器創建action方法:
… public static void listTagged(String tag) { Listposts = Post.findTaggedWith(tag); render(tag, posts); } …
如常,我們創建一個特定的路由來保持URI語義化:
GET /posts/{tag} Application.listTagged
我們遇到一個問題,因為這個路由跟之前的沖突了。這兩個路由將匹配同一個URI:
GET /posts/{id} Application.show GET /posts/{tag} Application.listTagged
不過,因為我們假設一個id是數值類型,而tag不是,我們可以簡單粗暴地用正則表達式解決問題:
GET /posts/{<[0-9]+>id} Application.show GET /posts/{tag} Application.listTagged
最后,我們需要創建/yabe/app/views/Application/listTagged.html模板,用于新的listTagged action:
#{extends "main.html" /} #{set title:"Posts tagged with " + tag /} *{********* Title ********* }* #{if posts.size() > 1}There are ${posts.size()} posts tagged "${tag}"
#{/if} #{elseif posts}There is 1 post tagged "${tag}"
#{/elseif} #{else}No post tagged "${tag}"
#{/else} *{********* Posts list *********}*#{list items:posts, as:"post"} #{display post:post, as:"teaser" /} #{/list}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64099.html
摘要:通過來實現一個基本的管理面板目前,我們還沒法使用博客的來寫新的文章,或修改評論。提供了一個即開即用的模塊,可以快速生成一個基本的管理面板。這是因為默認是以的輸出來得到一個模型對象的表示。在本教程的最后一章,你會學到關于本地化信息的更多東西。 通過CRUD來實現一個基本的管理面板 目前,我們還沒法使用博客的UI來寫新的文章,或修改評論。Play提供了一個即開即用的CRUD模塊,可以快速...
摘要:國際化和本地化完成了博客引擎后,我們來考慮額外的一件事應用的國際化和語言的本地化。國際化和本地化我們將分兩步討論,先是國際化,再是本地化。實際上,兩者是同步進行的你在國際化的同時,往往也是在本地化。 國際化和本地化 完成了博客引擎后,我們來考慮額外的一件事:Web應用的國際化和語言的本地化。雖然我們可以一開始就做這件事,但是最好還是先完成該應用的單一語言版本,然后再添加其他語言的支持...
摘要:完成應用測試我們已經完成了我們想要創建的博客引擎。當然我們已經完成了測試所有模型層的功能。評估代碼覆蓋率當然我們還沒有完成應用所需的所有測試用例。如你所見,我們遠遠沒有完成對應用的全面測試。 完成應用測試 我們已經完成了我們想要創建的博客引擎。不過這個項目尚未完全結束。為了保證代碼的質量,我們需要添加更多的測試。 當然我們已經完成了測試所有模型層的功能。所以博客引擎的核心功能已經被...
摘要:確保你的文本編輯器已經做了相應的配置。第一個,會自動監測源代碼的改變并在運行時自動重載。檢查下面的一行是否出現在應用日志中使用版本控制系統來追蹤變化當你開發一個項目時,最好使用版本控制系統來存儲你的源代碼。 Play是一個Java Web敏捷開發的框架http://www.playframework.com/documentation/1.2.7/home 之所以要翻譯這個教程,是因...
摘要:瀏覽和提交評論博客主頁現在已經完成,接下來要完成博客正文頁面。整個頁面將展示當前文章的所有評論,還包括一個用于提交新的評論的表單。刷新瀏覽器,檢查這次是否使用了正確的。給模板添加表單在后面試下提交新的評論。 瀏覽和提交評論 博客主頁現在已經完成,接下來要完成博客正文頁面。整個頁面將展示當前文章的所有評論,還包括一個用于提交新的評論的表單。 創建show action 要顯示文章內...
閱讀 3324·2023-04-25 16:25
閱讀 3837·2021-11-15 18:01
閱讀 1609·2021-09-10 11:21
閱讀 3016·2021-08-02 16:53
閱讀 3087·2019-08-30 15:55
閱讀 2494·2019-08-29 16:24
閱讀 2104·2019-08-29 13:14
閱讀 1037·2019-08-29 13:00