Grails在保存之前更新模型

时间:2014-03-29 12:54:41

标签: rest grails groovy

我无法根据用户的角色验证和重置某些字段。 我正在尝试使用grails开发一个rest api,当我尝试根据用户的角色重置某些字段时出现问题。我发送了一个带有所需"不允许"通过PUT更改为控制器。我将不允许的字段修改为对我来说正确的字段然后调用.save()和"不允许字段#34;字段使用其发送的值更新,而不是使用由我修改的值更新。这是代码。

模特

package phonebook

class User {
String firstName
String lastName
String phoneNo
String address
String email
String password
boolean active = false
String hash
String authToken = ""
String role = "user"

static hasMany = [contacts:Contact]

static constraints = {
    firstName(blank: false)
    lastName(blank: false)
    address(blank: true)
    phoneNo(unique: true)
    email(blank: false, unique: true)
    password(blank: false)
    role(blank: false, inList: ["user", "admin"])
    hash(blank: true)
    authToken(blank: true)
    active(inList:[true,false])
}
}

控制器的方法:

@Transactional
def update(User userInstance) {
    if (!isAuthenticated()){
        notAllowed()
        return
    }

    if (userInstance == null) {
        notFound()
        return
    }

    //if(isAdmin()){
       def userBackup = User.findById(userInstance.id)

       userInstance.role = userBackup.role
       userInstance.active = userBackup.active
       userInstance.hash = userBackup.hash
       userInstance.authToken = userBackup.authToken
    //}

    if (userInstance.hasErrors()) {
        respond userInstance.errors, view:'edit'
        return
    }

    userInstance.save flush:false

    request.withFormat {
        '*'{ respond userInstance, [status: OK] }
    }
}

JSON SENT VIA PUT

{
"id":"1",
"firstName": "Modified Name 23",
"role":"admin",
"active":"true",
"hash":"asdasd"
}

上述代码不应修改哈希值或活动或角色的值,即使它们已被发送。

有什么想法吗? 感谢。

3 个答案:

答案 0 :(得分:3)

保存更改的原因是因为默认情况下,对域实例所做的任何更改都将在会话结束时刷新。这被称为具有自动会话刷新功能的开放会话。我建议你对人们在GORM面临的一些主要问题上做some reading

正确使用discard可能会解决您的问题。退出控制器之前,请放弃实例更改。

例如:

if (!isAuthenticated()){
    notAllowed()
    userInstance.discard()
    return
}

修改

根据评论中的对话,这可能是解决您问题的方法。丢弃和附加的组合。

   userInstance.discard()
   def userBackup = User.findById(userInstance.id)

   userInstance.role = userBackup.role
   userInstance.active = userBackup.active
   userInstance.hash = userBackup.hash
   userInstance.authToken = userBackup.authToken
   userInstance.attach()

答案 1 :(得分:0)

我得到了这种方法的帮助。

getPersistentValue

实施例

 def update(ShopItem shopItemInstance) {

    if (shopItemInstance == null) {
        notFound()
        return
    }

    if (!shopItemInstance.itemPhoto){
        shopItemInstance.itemPhoto = 
                shopItemInstance.getPersistentValue("itemPhoto");
    }

    if (shopItemInstance.hasErrors()) {
        respond shopItemInstance.errors, view:'edit'
        return
    }


    shopItemInstance.save flush:true
    redirect(action: "show", id: shopItemInstance.id)
}

在你的情况下:

   userInstance.role = userInstance.getPersistentValue("role")
   userInstance.active = userInstance.getPersistentValue("active")
   userInstance.hash = userInstance.getPersistentValue("hash")
   userInstance.authToken = userInstance.getPersistentValue("authToken")

答案 2 :(得分:0)

如果您将使用命令对象功能,那就更好了。您可以将命令对象与请求有效负载绑定,对其进行验证,然后查找并更新域对象。

您可以在此处找到更多详细信息: http://grails.org/doc/2.3.x/guide/theWebLayer.html#commandObjects

根据记录,你不应该在你的控制器中使用@Transactional。您可以将该代码移动到服务中。

等式:

def update(Long id,UserCommand cmd){  // Grails会将json对象映射到命令对象中,如果使用@Validatable注释类,将调用validate()方法

}