Command Object representando hasMany
07/08/2014 12:19
0
Tenho um relacionamento hasMany dentro de uma domain e criei um command para representar meu formulário de cadastro/edição.

class Tarifa {
static hasMany = [valores: Valores]

List valores

String nome
}

class Valores {
static belongsTo = [tarifa: Tarifa]

BigDecimal valor
}

class GrupoCommand {
Long id //usado na edição
String nome
List<Valores> valores = [].withLazyDefault { new Valores(valor: 0) } //Crio um valor default para cada campo.

//Constraints

Tarifa criarTarifa() {
def tarifa = Tarifa.get(id) ?: new Tarifa()
tarifa.nome = nome
valores.each { valor -> tarifa.addTo(valor) }

return tarifa
}
}


O meu formulário de cadastro possui 30 campos que podem ser preenchidos com valores, portanto tenho algo assim dentro do form:


<g:each in="${0..29}" var="cont" status="i">
<input type="text" id="valor_${cont}" name="valores[${cont}].valor" value="${formatNumber(number: instance.valores[cont].valor, format: "#,##0.00#, locale: 'fr_FR')}" />
</g:each>


No cadastro tudo funciona perfeitamente, o meu problema é na edição de uma tarifa. O comportamento é ao cadastrar uma tarifa são cadastradas 30 valores, mas ao editar ele está inserindo 30 novos valores.

Segue minha action:

def salvarTarifa = {GrupoCommand cmd ->
if(cmd.validate()) {
def tarifa = cmd.criarTarifa()
tarifa.save()
flash.message = message(code: 'xpto')
redirect ...
return
}

render template: 'template', model: [instance: cmd] //renderiza as mensagens de erro.
}


Como posso resolver este problema? Sei que deve ser algo besta que estou fazendo mas me perdi na lógica, talvez possam me auxiliar.

Desde já agradeço as respostas.
Tags: command


0
Olá Carlos,
acho que nunca "criei um command para representar meu formulário de cadastro/edição.", então não sei se faz sentido o que vou dizer, mas observando sua domain e sua dificuldade relatada observei que além do
static hasMany = [valores: Valores]

da domain Tarifa, tem um
List valores

é isso mesmo? você tem vários Valores (domain Valores) e ainda uma lista de "Object" que está chamando de "valores" (não é uma Domain)
Isso pode estar gerando o problema, você não poderia remover o "List valores"?
07/08/2014 14:43


0
Entendi sua dúvida e não está errado a forma que criei, vou lhe explicar o porque.

Quando se cria um hasMany no grails, ele cria em nossa classe um Set com os valores do hasMany. Acontece que o Set não mantém a ordenação, por isso eu 'forço' a minha domain a usar o List quando for pegar os valores, pois preciso que estes valores não percam a ordem em que foram cadastrados.

Obrigado pela resposta.


0
Aaaaa, agora saquei ^^
Não sabia que dava pra fazer assim, depois que vc falou eu comentei com a turma aqui e me explicaram melhor esse comportamento, vivendo e aprendendo ;)

Nesse caso acho que o problema pode ser pq vc está passando apenas o campo "valor" ai quando chega na sua controller ela não consegue associar estes valores que estão chegando com os que ja existem na sua coleção, gerando a inserção de todos eles. Você ja pensou em colocar um campo "hidden" chamado "id" nesse "each" do GSP? assim vc consegue fazer este mapeamento na sua controller.

<g:each in="${0..29}" var="cont" status="i">
<g:hiddenField name="valores[${cont}].id" value="instance.valores[cont].id" />
<input type="text" id="valor_${cont}" name="valores[${cont}].valor" value="${formatNumber(number: instance.valores[cont].valor, format: "#,##0.00#, locale: 'fr_FR')}" />
</g:each>

esse código acima é só um exemplo, para ilustrar a ideia, não cheguei a testar.

outra coisa, seu save e update estão na mesma action? def salvarTarifa = {GrupoCommand cmd ->...

07/08/2014 18:25


0
Que bom Dyego.

Consegui resolver o problema usando um SortedSet, no lugar do list, o comportamento de cada um pode ser encontrado neste link

O que precisei fazer, foi usar esta abordagem.

Então implementei um comparable na minha domain e o problema foi quase resolvido.

Dentro do meu form, eu inseri uma tag hidden com o código do valor, quando era uma edição, com isso o grails faz a mágica sozinho, ele interpreta que ao salvar eu estou alterando os valores e não faz nada.

Segue a minha action completa de cadastro/edicao para você dar uma olhada.

def salvarGrupoTarifa = { GrupoTarifaCommand cmd -> 
flash.message = ""
if(cmd.validate()) {
def grupoTarifa = cmd.createGrupoTarifa();
grupoTarifa.save()

flash.message_list = message(code: 'tabelas.generico.salvo');
def estabelecimento = Estabelecimento.get(authenticateService.userDomain().estabelecimentoId)
render template: 'lista_grupo_tarifa', model: [lista: GrupoTarifa.findAllByEstabelecimentoAndStatusNotEqual(estabelecimento, "I")]

return
}

response.status = 500
render template: 'form_grupo_tarifa', model: [grupoTarifaInstance: cmd]
return
}


Att,





Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto