成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[翻譯]Play框架1.2.7版本教程(6) - 對(duì)添加標(biāo)簽的支持

bitkylin / 956人閱讀

摘要:對(duì)添加標(biāo)簽的支持隨著博客的文章越來(lái)越多,找到要找的文章越來(lái)越難。如果能夠添加標(biāo)簽,那就能更好地分類文章了。要在模式下啟動(dòng)應(yīng)用,輸入添加新的到類確保它能工作。為了保持高效,我們需要向初始數(shù)據(jù)集添加標(biāo)簽測(cè)試數(shù)據(jù)。修改來(lái)添加一些標(biāo)簽數(shù)據(jù)。

對(duì)添加標(biāo)簽的支持

隨著博客的文章越來(lái)越多,找到要找的文章越來(lái)越難。如果能夠添加標(biāo)簽,那就能更好地分類文章了。

Tag模型

我們將給博客的模型們添加新成員。對(duì)Tag類的定義是非常簡(jiǎn)單的:

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);
    }
}

因?yàn)橛袝r(shí)想要在需要時(shí)才創(chuàng)建標(biāo)簽,我們寫多一個(gè)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;
}
給文章打標(biāo)簽

現(xiàn)在是時(shí)候連接TagPost模型。讓我們給Post類添加相應(yīng)的關(guān)系:

…
@ManyToMany(cascade=CascadeType.PERSIST)
public Set tags;
 
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來(lái)保持一個(gè)有序的標(biāo)簽列表。(由于我們之前的compareTo實(shí)現(xiàn),按的是字母順序)

我們將保持該關(guān)系為單向關(guān)系。

我們將給Post類添加一系列輔助函數(shù)。第一個(gè)用于給Post打標(biāo)簽:

…
public Post tagItWith(String name) {
    tags.add(Tag.findOrCreateByName(name));
    return this;
}
…

下一個(gè)是根據(jù)指定標(biāo)簽查找所有文章:

…
public static List findTaggedWith(String tag) {
    return Post.find(
        "select distinct p from Post p join p.tags as t where t.name = ?", tag
    ).fetch();
}
…

是時(shí)候?qū)懸粋€(gè)新的測(cè)試用例了。要在test模式下啟動(dòng)應(yīng)用,輸入:

$ play test

添加新的@TestBasicTest類:

@Test
public void testTags() {
    // Create a new user and save it
    User bob = new User("[email protected]", "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());
}

確保它能工作。

解決難題

如果你想要根據(jù)多個(gè)標(biāo)簽來(lái)查找相應(yīng)的文章,該怎么辦?這個(gè)問題比表面看上去要難。

我將直接給你所需的JPQL查詢語(yǔ)句:

…
public static List findTaggedWith(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();
}
…

代碼的關(guān)鍵在于,我們需要使用一個(gè)having count語(yǔ)句來(lái)從連結(jié)產(chǎn)生的視圖中過濾出擁有全部標(biāo)簽的文章。

注意這里我們不能用Post.find("...", tags, tags.count)語(yǔ)法,因?yàn)?b>tags是一個(gè)變長(zhǎng)參數(shù)

你可以在前一個(gè)測(cè)試中加入更多的檢查來(lái)測(cè)試它:

…
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());
…
標(biāo)簽集合

我們最好有一個(gè)標(biāo)簽集合來(lái)看看有哪些標(biāo)簽。讓我們給Tag類添加一個(gè)方法來(lái)生成標(biāo)簽集合:

public static List getCloud() {
    List result = Tag.find(
        "select new map(t.name as tag, count(p.id) as pound) from Post p join p.tags as t group by t.name order by t.name"
    ).fetch();
    return result;
}

這里,我們使用Hibernate的一個(gè)允許我們從JPA查詢中返回自定義對(duì)象的特性。返回的結(jié)果是一個(gè)Map列表,其中每個(gè)Map包括標(biāo)簽名(鍵)和標(biāo)簽個(gè)數(shù)(值)。

在我們前面的測(cè)試中加多一個(gè)檢查:

…
List cloud = Tag.getCloud();
assertEquals(
    "[{tag=Blue, pound=1}, {tag=Green, pound=1}, {tag=Red, pound=2}]",
    cloud.toString()
);
向博客界面添加標(biāo)簽

現(xiàn)在我們又多了一個(gè)瀏覽文章的方式了。為了保持高效,我們需要向初始數(shù)據(jù)集添加標(biāo)簽測(cè)試數(shù)據(jù)。

修改/yabe/conf/initial-data.yml來(lái)添加一些標(biāo)簽數(shù)據(jù)。比如:

…
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的定義,因?yàn)樗鼈儠?huì)被Post用到。

你需要重啟應(yīng)用來(lái)加載新的初始數(shù)據(jù)。注意Play甚至?xí)嬖V你出現(xiàn)在YAML文件中的問題:

然后修改#{display /}標(biāo)簽,在全文模式下展示標(biāo)簽集合。修改/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}
    
#{/elseif}
…

標(biāo)簽頁(yè)面

現(xiàn)在我們可以實(shí)現(xiàn)通過標(biāo)簽瀏覽文章了。在#{display /}標(biāo)簽,之前,我們留下一個(gè)空鏈接;現(xiàn)在終于可以用listTagged action補(bǔ)完它(修改yabe/app/views/tags/display.html):

…
- Tagged
#{list items:post.tags, as:"tag"}
    ${tag}${tag_isLast ? "" : ", "}
#{/list}
…

Application控制器創(chuàng)建action方法:

…
public static void listTagged(String tag) {
    List posts = Post.findTaggedWith(tag);
    render(tag, posts);
}
…

如常,我們創(chuàng)建一個(gè)特定的路由來(lái)保持URI語(yǔ)義化:

GET     /posts/{tag}                    Application.listTagged

我們遇到一個(gè)問題,因?yàn)檫@個(gè)路由跟之前的沖突了。這兩個(gè)路由將匹配同一個(gè)URI:

GET     /posts/{id}                     Application.show
GET     /posts/{tag}                    Application.listTagged

不過,因?yàn)槲覀兗僭O(shè)一個(gè)id是數(shù)值類型,而tag不是,我們可以簡(jiǎn)單粗暴地用正則表達(dá)式解決問題:

GET     /posts/{<[0-9]+>id}             Application.show
GET     /posts/{tag}                    Application.listTagged

最后,我們需要?jiǎng)?chuàng)建/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}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64099.html

相關(guān)文章

  • [翻譯]Play框架1.2.7版本教程(7) - 通過CRUD來(lái)實(shí)現(xiàn)一個(gè)基本管理面板

    摘要:通過來(lái)實(shí)現(xiàn)一個(gè)基本的管理面板目前,我們還沒法使用博客的來(lái)寫新的文章,或修改評(píng)論。提供了一個(gè)即開即用的模塊,可以快速生成一個(gè)基本的管理面板。這是因?yàn)槟J(rèn)是以的輸出來(lái)得到一個(gè)模型對(duì)象的表示。在本教程的最后一章,你會(huì)學(xué)到關(guān)于本地化信息的更多東西。 通過CRUD來(lái)實(shí)現(xiàn)一個(gè)基本的管理面板 目前,我們還沒法使用博客的UI來(lái)寫新的文章,或修改評(píng)論。Play提供了一個(gè)即開即用的CRUD模塊,可以快速...

    騫諱護(hù) 評(píng)論0 收藏0
  • [翻譯]Play框架1.2.7版本教程(12) - 國(guó)際化和本地化

    摘要:國(guó)際化和本地化完成了博客引擎后,我們來(lái)考慮額外的一件事應(yīng)用的國(guó)際化和語(yǔ)言的本地化。國(guó)際化和本地化我們將分兩步討論,先是國(guó)際化,再是本地化。實(shí)際上,兩者是同步進(jìn)行的你在國(guó)際化的同時(shí),往往也是在本地化。 國(guó)際化和本地化 完成了博客引擎后,我們來(lái)考慮額外的一件事:Web應(yīng)用的國(guó)際化和語(yǔ)言的本地化。雖然我們可以一開始就做這件事,但是最好還是先完成該應(yīng)用的單一語(yǔ)言版本,然后再添加其他語(yǔ)言的支持...

    hoohack 評(píng)論0 收藏0
  • [翻譯]Play框架1.2.7版本教程(10) - 完成應(yīng)用測(cè)試

    摘要:完成應(yīng)用測(cè)試我們已經(jīng)完成了我們想要?jiǎng)?chuàng)建的博客引擎。當(dāng)然我們已經(jīng)完成了測(cè)試所有模型層的功能。評(píng)估代碼覆蓋率當(dāng)然我們還沒有完成應(yīng)用所需的所有測(cè)試用例。如你所見,我們遠(yuǎn)遠(yuǎn)沒有完成對(duì)應(yīng)用的全面測(cè)試。 完成應(yīng)用測(cè)試 我們已經(jīng)完成了我們想要?jiǎng)?chuàng)建的博客引擎。不過這個(gè)項(xiàng)目尚未完全結(jié)束。為了保證代碼的質(zhì)量,我們需要添加更多的測(cè)試。 當(dāng)然我們已經(jīng)完成了測(cè)試所有模型層的功能。所以博客引擎的核心功能已經(jīng)被...

    _Dreams 評(píng)論0 收藏0
  • [翻譯]Play框架1.2.7版本教程(1)

    摘要:確保你的文本編輯器已經(jīng)做了相應(yīng)的配置。第一個(gè),會(huì)自動(dòng)監(jiān)測(cè)源代碼的改變并在運(yùn)行時(shí)自動(dòng)重載。檢查下面的一行是否出現(xiàn)在應(yīng)用日志中使用版本控制系統(tǒng)來(lái)追蹤變化當(dāng)你開發(fā)一個(gè)項(xiàng)目時(shí),最好使用版本控制系統(tǒng)來(lái)存儲(chǔ)你的源代碼。 Play是一個(gè)Java Web敏捷開發(fā)的框架http://www.playframework.com/documentation/1.2.7/home 之所以要翻譯這個(gè)教程,是因...

    solocoder 評(píng)論0 收藏0
  • [翻譯]Play框架1.2.7版本教程(4) - 瀏覽和提交評(píng)論

    摘要:瀏覽和提交評(píng)論博客主頁(yè)現(xiàn)在已經(jīng)完成,接下來(lái)要完成博客正文頁(yè)面。整個(gè)頁(yè)面將展示當(dāng)前文章的所有評(píng)論,還包括一個(gè)用于提交新的評(píng)論的表單。刷新瀏覽器,檢查這次是否使用了正確的。給模板添加表單在后面試下提交新的評(píng)論。 瀏覽和提交評(píng)論 博客主頁(yè)現(xiàn)在已經(jīng)完成,接下來(lái)要完成博客正文頁(yè)面。整個(gè)頁(yè)面將展示當(dāng)前文章的所有評(píng)論,還包括一個(gè)用于提交新的評(píng)論的表單。 創(chuàng)建show action 要顯示文章內(nèi)...

    AWang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<