Grails 非常支持将请求参数绑定到域对象及其关联.这在很大程度上依赖于检测.id以数据库结束并自动加载数据库的请求参数.
但是,目前尚不清楚如何填充命令对象的关联.请看以下示例:
class ProductCommand {
String name
Collection<AttributeTypeCommand> attributeTypes
ProductTypeCommand productType
}
Run Code Online (Sandbox Code Playgroud)
该对象具有单端关联ProductTypeCommand和多端关联AttributeTypeCommand.所有属性类型和产品类型的列表都可从此接口的实现中获得
interface ProductAdminService {
Collection<AttributeTypeCommand> listAttributeTypes();
Collection<ProductTypeCommand> getProductTypes();
}
Run Code Online (Sandbox Code Playgroud)
我使用此界面填充GSP中的产品和属性类型选择列表.我还依赖 - 将此接口注入命令对象,并使用它来"模拟" 命令对象attributeTypes和productType属性
class ProductCommand {
ProductAdminService productAdminService
String name
List<Integer> attributeTypeIds = []
Integer productTypeId
void setProductType(ProductTypeCommand productType) {
this.productTypeId = productType.id
}
ProductTypeCommand getProductType() {
productAdminService.productTypes.find {it.id == productTypeId}
}
Collection<AttributeTypeCommand> getAttributeTypes() {
attributeTypeIds.collect {id ->
productAdminService.getAttributeType(id)
}
}
void setAttributeTypes(Collection<AttributeTypeCommand> attributeTypes) {
this.attributeTypeIds …Run Code Online (Sandbox Code Playgroud) 这是我想做的事情:
class A {
String string
static constraints = {
string(maxSize:100)
}
}
class B extends A {
static constraints = {
string(url:true)
}
}
Run Code Online (Sandbox Code Playgroud)
所以A类应该有一些约束,B应该对同一个属性有相同的附加约束.
我无法让它工作,我可以想象它会与Table-per-Hierarchy概念发生冲突.
所以我尝试通过引入一个带有类B的约束的Command对象来解决这个问题,这些约束可以在类B的构造函数中进行验证.但似乎Command对象只能在控制器中使用(grails一直说没有.validate ()方法).
所以我的问题是:使用grails约束解决这个问题最优雅的方法是什么(不是手动重新实现验证)?可能...
编辑:我可以定义子类中的所有约束,重复父类的约束,或者根本不在父类中有约束.但是该解决方案应该适用于同一父类的多个子类(具有不同约束).
I have a class called LoginCommand in domain/my/package/name
class LoginCommand {
String emailAddress
String password
}
Run Code Online (Sandbox Code Playgroud)
My question is why is a table be auto generated in my database for a***Command object in grails? Are these command objects supposed to be placed ouside of /domain to avoid auto generation of a table by hibernate/orm.
在我的grails应用程序中,我有一个外部命令对象,其中包含其他命令对象的列表:
public class OuterCommand {
List<InnerCommand> innerCommands = ListUtils.lazyList([], FactoryUtils.instantiateFactory(InnerCommand))
}
class InnerCommand {
String code
Long id
String value
static constraints = {
code(nullable: false, blank: false)
value(nullable: false, blank: false)
}
}
Run Code Online (Sandbox Code Playgroud)
相当不寻常的实例化innerCommands是基于这个建议.但是,我发现如果我调用validate()一个实例OuterCommand,验证似乎不会验证包含的实例InnerCommand.
是否可以嵌套命令对象并validate()在最外层对象上调用时验证命令对象的整个图形?
谢谢,唐
我提交了一个日期(作为字符串).我想将它映射到命令对象.我已经看了很多,并没有发现如何在命令对象中实现这种映射到实际日期的很好的资源.
如果我在控制器本身中执行此操作,我可以执行以下操作,但这不允许我轻松映射到我的命令对象.
def endDate = params.date('endDate', 'MM/dd/yyyy')
Run Code Online (Sandbox Code Playgroud)
对于我的命令对象,我能够得到的最接近的是覆盖日期对象的getter和setter.两者都需要被覆盖,否则不使用setter.这是我第一次尝试(将String设置为Date,但获取Date).所以这不使用setter:
@grails.validation.Validateable
class TaskCreateCommand {
Date startDate
public void setStartDate(String dateStr){
this.start = Date.parse('MM/dd/yyyy', dateStr)
}
}
Run Code Online (Sandbox Code Playgroud)
这不会给出任何运行时问题,但是没用,因为我无法提取实际的Date对象.
@grails.validation.Validateable
class TaskCreateCommand {
Date startDate
public void setStartDate(String dateStr){
this.start = Date.parse('MM/dd/yyyy', dateStr)
}
public String getStartDate(){
return start.toString()
}
}
Run Code Online (Sandbox Code Playgroud) 我正在使用grails 2.2.1并尝试验证嵌套的命令结构.这是我的命令对象的简化版本:
@Validateable
class SurveyCommand {
SectionCommand useful
SectionCommand recommend
SurveyCommand() {
useful = new SectionCommand(
question: 'Did you find this useful?',
isRequired: true)
recommend = new SectionCommand(
question: 'Would you recommend to someone else?',
isRequired: false)
}
}
@Validateable
class SectionCommand {
String question
String answer
boolean isRequired
static constraints = {
answer(validator: answerNotBlank, nullable: true)
}
static answerNotBlank = { String val, SectionCommand obj ->
if(obj.isRequired) {
return val != null && !val.isEmpty()
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试验证SurveyCommand …
我试图弄清楚如何将JSON请求中的嵌套对象反序列化并验证到Grails 2.1.1命令对象中.
目前我的控制器中有一个命令对象,它有一些基本属性,然后是域对象列表,
protected static class CustomCommand {
String name
String description
List<DomainObject> objs
}
Run Code Online (Sandbox Code Playgroud)
和我的POST请求的JSON正文,
{
name: 'test name',
description: 'test description',
objs: [
{
name: 'test sub object',
description: 'test description'
}
]
}
Run Code Online (Sandbox Code Playgroud)
我看到用空数组创建的命令对象.知道如何在JSON主体中获取子对象以反序列化到命令对象然后验证它们吗?
以前我通过从参数映射手动创建一个对象并直接验证它来解决这个问题,但这感觉就像一个没有利用Grails提供的所有功能的解决方法.
我正在尝试测试具有数据绑定的Command对象的Controller.
命令对象注入了一个服务.
但是当我尝试测试命令对象时,从未找到注入的服务方法,因为它从未被"注入"
有没有办法在命令对象中模拟服务?
测试方法
void testLoginPasswordInvalid() {
mockRequest.method = 'POST'
mockDomain(User, [new User(login:"freddy", password:"realpassword")])
mockLogging(UserService) // userService mocked
MockUtils.prepareForConstraintsTests(LoginCommand)
def userService = new UserService()
def user = userService.getUser("freddy")//Gets called and returns the mockDomain
assert userService.getUser("freddy")//Passes
def cmd = new LoginCommand(login:"freddy", password:"letmein")
cmd.validate() // Fails (userService is nevr injected)
controller.login(cmd)
assertTrue cmd.hasErrors()
assertEquals "user.password.invalid", cmd.errors.password
assertEquals "/store/index", renderArgs.view
}
Run Code Online (Sandbox Code Playgroud)
找不到userService的getUser()方法
Cannot invoke method getUser() on null object
java.lang.NullPointerException: Cannot invoke method getUser() on null object
Run Code Online (Sandbox Code Playgroud)
码
调用控制器的登录方法,
def login = …Run Code Online (Sandbox Code Playgroud) 我正在使用一个应用程序grails version 2.3.9.在那里,我正在使用复选框呈现列表.用户可以选择任何行并提交页面.在服务器端,我使用命令对象来绑定数据.
我的命令对象 -
@Validateable
class MyCO {
List<MyDoamin> myDomains = ListUtils.lazyList([], FactoryUtils.instantiateFactory(MyDoamin))
...
static constraints = {
myDomains nullable: false, validator: { val, obj ->
if (val.size() < 1) {
return "error.code"
}
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
视图 -
<g:each in="${myDomains}" var="myDomain" status="idx">
<tr>
<td>
<input type="checkbox" name="myDomains[${idx}].id" value="${myDomain.id}" checked>
</td>
...
</tr>
</g:each>
Run Code Online (Sandbox Code Playgroud)
行动 -
def myAction(MyCO myCO) {
if (myCO.validate()) {
...
} else {
log.error "-----INVALID-----"
...
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常.但是,如果用户选择其索引(idx)值大于255的行,则数据绑定不起作用.
请求参数 -
[myDomains …
如果我错过了一些非常明显的东西,我很抱歉,但是我一直在用这个问题解决问题.
我有一个命令对象:
class MyCommand {
Long id
String value
}
Run Code Online (Sandbox Code Playgroud)
我在我的控制器中绑定到这个:
public update(MyCommand myCmd) {
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,一切都很好.现在我正在尝试添加版本字段,该字段在请求参数中传递给命令对象:
class MyCommand {
Long id
Long version
String value
}
Run Code Online (Sandbox Code Playgroud)
现在,当绑定发生时,id和version始终为null,即使它们存在于params对象中.
我怀疑对于与grails如何处理乐观锁定相关的id/version属性可能有一些特殊处理(因为这最终是我这样做的原因)但是问题出现在命令对象中,与任何域对象无关.
我很困惑,为什么这不起作用.在命令对象上存在版本时是否存在某些特殊情况?
command-objects ×10
grails ×10
groovy ×4
data-binding ×2
binding ×1
constraints ×1
grails-2.0 ×1
grails-2.3 ×1
gsp ×1
inheritance ×1
junit ×1
service ×1
subclass ×1
unit-testing ×1