Я новичок в Grails и столкнулся с трудной проблемой отношения «многие ко многим».
Вот упрощенные классы домена:
class Comment {
String title
String comment
static hasMany = [commentGroups:CommentGroup]
static constraints = {
title blank:true
comment blank:false, maxSize:800
}
static mapping = {
commentGroups cascade: "all-delete-orphan"
}
}
class CommentGroup {
String groupTitle
static hasMany = [comments:Comment]
static belongsTo = Comment
static constraints = {
groupTitle blank:true, nullable:true
}
}
Вот html-выдержка из формы, которая динамически создается с использованием JS. ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ, ЧТО ВСЕ ПРИВЕДЕННЫЙ КОД НЕ ЗАВЕРШЕН, ЭТО ТОЛЬКО ДЛЯ того, чтобы дать вам представление о том, что мне нужно для достижения:
<form class="m-b-d" role="form" name="comments" id="comments" method="post" action="/rootstofood/comment/save">
<div class="form-group has-feedback col-sm-12">
<label for="rating" class="control-label">Give us a star rating?</label>
<div class="br-wrapper br-theme-bootstrap-stars">
<select aria-describedby="Rating" name="rating" id="rating" class="form-control input-lg" style="display: none;">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<div class="br-widget"><a href="#" data-rating-value="1" data-rating-text="1"><span></span></a><a href="#" data-rating-value="2" data-rating-text="2"><span></span></a><a href="#" data-rating-value="3" data-rating-text="3"><span></span></a><a href="#" data-rating-value="4"
data-rating-text="4"><span></span></a><a href="#" data-rating-value="5" data-rating-text="5"><span></span></a>
<div class="br-current-rating"></div>
</div>
</div>
</div>
<div class="form-group has-feedback col-sm-12">
<label for="commentTitle" class="control-label sr-only">Any short comment header?</label>
<input aria-describedby="Comment title" placeholder="Any short comment header?" value="" id="commentTitle" name="commentTitle" class="form-control input-lg" maxlength="200">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="commentTitle">(success)</span>
</div>
<div class="form-group has-feedback col-sm-12">
<label for="startComment" class="control-label sr-only">Start comment</label>
<textarea rows="3" aria-describedby="Start comment" placeholder="Enter start comment" id="startComment" name="startComment" class="form-control input-lg vrequired" maxlength="400"></textarea>
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="startComment">(success)</span>
</div>
<!-- Children or staff comments area START -->
<!-- ##### Dynamic area START #### -->
<div class="col-sm-12" id="comment-groups">
<div class="panel panel-default p-trbl" data-group-id="0" id="comment-group-0" data-remove-group-id="0">
<div class="ovh">
<div class="pull-left"><b>Comment Group: 0</b>
</div><a class="danger pull-right remove-comment-group" data-remove-group-id="0" href="#"><span class="glyphicon glyphicon-remove-sign"></span> Remove</a>
</div>
<div class="panel-body">
<div class="form-group has-feedback col-sm-12">
<label for="title" class="control-label sr-only">Any short comment header?</label>
<input aria-describedby="Comment Group title" placeholder="Any short comment group header?" value="" name="commentGroups[0].groupTitle" class="form-control input-lg" maxlength="200">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="title">(success)</span>
</div>
<!-- Children or staff comments area START -->
<div class="col-sm-12" data-comments-group-id="0" id="comments">
<div class="panel panel-default p-trbl" data-comment-group-id="GROUP" id="comment-0_0">
<div class="ovh">
<div class="pull-left"><b>Staff/Pupil Group/Comment: 0</b>
</div><a class="danger pull-right remove-comment" data-remove-comment-id="0_0" href="#"><span class="glyphicon glyphicon-remove-sign"></span> Remove</a>
</div>
<div class="panel-body">
<div class="form-group has-feedback col-sm-12">
<label for="startComment" class="control-label sr-only">Comment</label>
<textarea id="commentGroups[0].comments[0].startComment" rows="3" aria-describedby="Comment" placeholder="Enter comment" name="commentGroups[0].comments[0].startComment" class="form-control input-lg vrequired" maxlength="400"></textarea>
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="comment">(success)</span>
</div>
<div class="form-group has-feedback col-sm-10">
<label for="name" class="control-label sr-only">Name</label>
<input type="text" aria-describedby="Name" placeholder="Name" name="commentGroups[0].comments[0].name" class="form-control input-lg vrequired" maxlength="30">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="name">(success)</span>
</div>
<div class="form-group has-feedback col-sm-2">
<label for="type" class="control-label sr-only">Comment from</label>
<select aria-describedby="Type" name="commentGroups[0].comments[0].type" id="type" class="form-control input-lg">
<option value="Parent">Parent</option>
<option value="Pupil">Pupil</option>
<option value="Staff">Staff</option>
<option value="KS1">KS1</option>
<option value="KS2">KS2</option>
<option value="Other">Other</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-group has-feedback col-sm-12">
<a data-comment-group-id="0" class="add-comment success" href="#"><span class="glyphicon glyphicon-plus-sign"></span> Add another pupil or staff comment</a>
</div>
<!-- Children or staff comments area END -->
</div>
</div>
</div>
<div class="form-group has-feedback col-sm-12">
<a class="add-group success" href="#"><span class="glyphicon glyphicon-plus-sign"></span> Add another comment group</a>
</div>
<!-- Children or staff comments area END -->
<div class="form-group has-feedback col-sm-12">
<label for="endComment" class="control-label sr-only">End comment</label>
<textarea rows="3" aria-describedby="End comment" placeholder="Enter end comment" id="endComment" name="endComment" class="form-control input-lg" maxlength="400"></textarea>
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="endComment">(success)</span>
</div>
<div class="form-group has-feedback col-sm-2">
<label for="title" class="control-label sr-only">Title</label>
<select aria-describedby="Title" name="title" id="title" class="form-control input-lg">
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
<option value="Ms">Ms</option>
<option value="Miss">Miss</option>
<option value="Mr & Mrs">Mr & Mrs</option>
</select>
</div>
<div class="form-group has-feedback col-sm-10">
<label for="firstName" class="control-label sr-only">Name</label>
<input type="text" aria-describedby="Name" placeholder="Name" id="name" name="name" class="form-control input-lg vrequired" maxlength="60">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="Name">(success)</span>
</div>
<div class="form-group has-feedback col-sm-12">
<label for="jobTitle" class="control-label sr-only">Job title</label>
<input type="text" aria-describedby="Job title" placeholder="Job title" id="jobTitle" name="jobTitle" class="form-control input-lg" maxlength="60">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="jobTitle">(success)</span>
</div>
<div class="form-group has-feedback col-sm-12">
<label for="organisation" class="control-label sr-only">Organisation</label>
<input type="text" aria-describedby="Organisation" placeholder="Organisation" id="organisation" name="organisation" class="form-control input-lg" maxlength="60">
<span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
<span class="sr-only" id="organisation">(success)</span>
</div>
<div class="form-group has-feedback col-sm-2">
<label for="type" class="control-label sr-only">Type</label>
<select aria-describedby="Type" name="type" id="type" class="form-control input-lg">
<option value="Parent">Parent</option>
<option value="Pupil">Pupil</option>
<option value="Staff">Staff</option>
<option value="KS1">KS1</option>
<option value="KS2">KS2</option>
<option value="Other">Other</option>
</select>
</div>
<div class="col-md-12">
<button class="btn btn-default btn-lg onWht" id="feedback" type="submit"><b>Submit Feedback <span class="glyphicon glyphicon-chevron-right"></span></b>
</button>
</div>
</form>
Вот мое незавершенное действие по сохранению контроллера, которое почти готово:
def save() {
def commentInstance = new Comment(params)
if (!commentInstance.save(flush: true)) {
render(view: "index", model: [commentInstance: commentInstance])
return
}
render(view: "thankyou")
}
Итак, из кода у меня есть родительский домен «Комментарий», в котором много «Групповых комментариев», в котором много «Комментариев».
Когда я создаю свой проект, моя база данных дает мне следующие таблицы:
comment
comment_comment_groups
comment_group
Что меня удивило, так как я установил отношение «многие ко многим», поэтому ожидал:
comment
comment_comment_groups
comment_group_comments
comment_group
Я, вероятно, ожидаю, что Grails сделает здесь слишком много работы. Поэтому, когда я отправляю форму комментариев, база данных заполняется моим родительским «Комментарием» и даже доменами «CommentGroup», принадлежащими «Комментарию», но комментарии «CommentGroup» не сохраняются в базе данных.
Я понимаю, что здесь я наивен, но что я упускаю? Может ли кто-нибудь помочь, поскольку я искал повсюду и не мог найти подобный сценарий. Я знаю, что существует множество примеров отношений «многие ко многим», но ни один из них не охватывает мой сценарий.
А пока продолжу поиск.
Я предполагаю, что мне нужно создать более сложное действие «сохранить» в моем контроллере, вручную обрабатывая параметры, но было бы хорошо, если бы для этого существовал способ GORM.
С нетерпением жду ответа ... пожалуйста, будьте нежны со мной :-)
Заранее спасибо.