我们必须做的第一件事,是安装搜索插件。
grails install-plugin searchable
static hasMany = [followed:Person, status:Status]
static searchable = [only: 'realName']
Person.groovy
package org.grails.twitter
class Person {
transient springSecurityService
String realName
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static hasMany = [followed:Person, status:Status]
static searchable = [only: 'realName']
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set
getAuthorities() {
PersonAuthority.findAllByPerson(this).collect { it.authority } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
我们在<body>之后添加这些代码。
Search For People To Follow
完整的代码应该看起来像这样:
index.gsp
What Are You Doing?
Search For People To Follow
What Are You Doing?
我们现在在浏览器中检查我们的应用程序。可以看到一个名为SearchableController的新控制器。此控制器将处理所有搜索请求。这是由搜索插件创建的。
我们可以看到在我们状态视图中有一个新的文本域,这是一个我们刚才添加的。当我们搜索一个人,例如说“john”(john在记录中已经存在),然后在键盘上回车,我们就会被重定向到搜索结果页面。
然而,我们希望更改结果会更好看一点。通过覆写搜索控制器的视图来实现。
在grails-app/views目录下,我们创建一个新文件夹并命名为“searchable”。这个文件夹里面,我们创建一个新文件,并命名为“index.gsp”。
这是index.gsp文件的内容。
index.gsp
${person.realName}
follow
在页面中我们看到一个搜索结果。后面还提供了一个链接,用于跟踪某一个用户。
我们现在在浏览器再次打开应用程序。
正如我们所看到的,搜索结果页面已经更新。
然而,当我们点击链接,出现一个错误404。这背后的原因是,我们没有在StatusController.groovy里面定义链接的方法,用于在此控制器来处理链接事件。
def follow = {
def per = Person.get(params.id)
if(per) {
def currentUser = lookupPerson()
currentUser.addToFollowed(per)
currentUser.save()
}
redirect action: 'index'
}
我们这段代码添加在index() 闭包之后。该方法只是根据链接用户的ID找到与之关联的其他用户,然后将用户重定向到index.gsp。
当我们再一次检查和刷新应用程序,可以看到,当我们点击跟随,我们不再遇到错误了。我们是那么重定向到状态索引页之后。虽然我们没有看到它,但我们现在就是john。
让我们打开不同的浏览器用john名字登录。
我们发布一个新的状态信息并看看yancy的时间轴会发生什么。
这是john的时间轴。
这yancy时间轴。当我们刷新页面,yancy在john之后发布了一个新状态,似乎我们仍然没有看到john的状态更新即使我们跟着他。
要解决这个问题,我们需要更新StatusController.groovy里面的currentUserTimeline()方法,我们添加了一个新的判断,用于判断搜索结果。在判断作者的代码之后,我们添加下面一行:
if(per.followed) author in per.followed
现在,在搜索结果中包括了搜索所有用户的状态。
更新后的文件应该看起来像这样:
StatusController.groovy
package org.grails.twitter
import grails.plugins.springsecurity.Secured
@Secured('IS_AUTHENTICATED_FULLY')
class StatusController {
def springSecurityService
def index() {
def msgs = currentUserTimeline()
return [messages: msgs] // this is a map. key=>value
}
def follow = {
def per = Person.get(params.id)
if(per) {
def currentUser = lookupPerson()
currentUser.addToFollowed(per)
currentUser.save()
}
redirect action: 'index'
}
def updateStatus = {
def status = new Status(message: params.message)
status.author = lookupPerson()
status.save()
def messages = currentUserTimeline()
render template: 'messages', collection: messages, var: 'message'
}
private lookupPerson() {
Person.get(springSecurityService.principal.id)
}
private currentUserTimeline() {
def per = lookupPerson()
def query = Status.whereAny {
author { username == per.username }
if(per.followed) author in per.followed
}.order 'dateCreated', 'desc'
def messages = query.list(max: 10)
messages
}
}
在本教程的最后一部分,我们会优化我们的Web应用程序并添加一些额外的功能。