Grails relating values from two different domains in a custom view - grails

While I'm experienced with Java, I am a Grails newbie but I am trying to get into it. I set up a basic "School" application containing the following domains:
Student
Class
Attendance
Both the 'Student' and 'Class' domains are scaffolded. Now, I want to create the 'Attendance' domain, and I'm going to need a controller with a custom view. I can do that, I'm just looking to understand (at a high level) the best way to set up the view (let's call it 'attendance.gsp').
The view will contain a dropdown box to select a class. Once a class is selected, I want to populate a table. The first column will contain the list of students in the class, and the second column will contain "Attended?" checkboxes.
I think that I can at least get that far.
I am wondering how to go about relating the checkbox value to the student. Since this class is not scaffolded, no attendance column has been created in the database. Do I need to have anything defined in the Attendance domain? How might you go about doing this? Can anyone recommend a particular example online that is doing something similar?
Thanks!

Something like this:
class Class {
...
static hasMany = [sessionsAttendance: Attendance]
}
class Student {
....
}
class Attendance {
static hasMany = [studentsAttended: Student]
}

Related

Grails: How do i select from a list of previously created objects in my view?

Let's say i have the following classes:
package test
class Person {
String name
static hasMany = [stuff:Stuff]
static constraints = {
}
}
and
package test
class Stuff {
String stuff
static belongsTo = Person
static constraints = {
}
}
When i implement the view for Person i want to be able to select from a list of previously created stuff. How do i achieve that? I see that, when i use scaffolding Grails generates that drop down menu where i can do that but since i a designing my own views i would like to understand how that is done.
Thank you.
Probably good to start be reviewing the documentation for the select tag here: https://gsp.grails.org/latest/ref/Tags/select.html
A simple example to present a list of all Stuff would look like:
<g:select name="stuffSelect" from="${Stuff.list()}" optionKey="id" optionValue="stuff"/>
This should give you a dropdown of all Stuff in your database, displaying the String value to the user, but submitting the DB ID when the form submits.
I'm pretty sure you can use the generate-all command in grails, to see what the scaffolding code looks like:
http://docs.grails.org/3.1.1/ref/Command%20Line/generate-all.html
Using this command should generate Controllers, views, etc. so you can see how the scaffolded code works. Don't worry about being able to go back to generated scaffold code, just delete the stuff created by generate-all, and grails will autogenerate it at runtime like it does now.

Grails binding one to one associations

When you generate grails views, grails looks at your relationships and generates the right html for your form data to be automatically binded to the back end domain. For one to one associations grails creates a drop down list.
However, you might not want to present that property as a drop down list but something more custom (for example a text field with autocomplete). As soon as you do that the value that comes to the controller from that field, comes in as a String and you have to first:
Clear errors
Perform a findBy based on a given param and assign it to the property of the domain
I really want to avoid doing findBys in the controller as much as possible because it seems like I am doing logic/things that should not go there. The controller should delegate to the Service layer. It is not clear to me from the grails documentation how would I do that by using bindData which seems to work really well with String, date, Integer properties etc.. but I do not see how bindData is used for properties that are other domains.
I also really want to avoid passing the params object to the Service layer as it seems less reusable (or maybe not, correct me if I am wrong). I guess that I do not like how it looks semantically. I would prefer the first over the second:
#Transactional
class WithdrawService {
def addWithdraw(Withdraw withdraw) {
//perform business logic here
}
def createWithdraw(Map params){
//perform business logic here
}
}
Let's take the following example:
class Withdraw {
Person person
Date withdrawDate
}
and the parent lookup table
class Person {
String name
String lastName
static constraints = {
}
#Override
public String toString() {
return "$name $lastName"
}
}
In order for the bind to happen automatically without any extra work grails passes in the following request params to automatically bind the one to one:
person.id
a person map with the id.
[person.id:2, person:[id:2], withdrawDate:date.struct, withdrawDate_month:11, create:Create, withdrawDate_year:2015, withdrawDate_day:10, action:save, format:null, controller:withdraw]
What is the best way to go about this?
Pass two hidden fields that look exactly like this: person.id:2, person:[id:2] that get populated as a result of the Ajax call that populates the autocomplete?
In the controller do a Person.findBySomeKnownProperty(params.someKnownValue)
Or any other approach?

Adding child elements onto a domain object before the domain object is created

(Sorry if this is a noob question, I couldn't find the answers on the grails reference)
I have the following domain heirarchy :
User > (has many) Survey > (has many) SurveyQuestion > (has many) SurveyQuestionResponse
These are two of the above :
class Survey {
String surveyName
static hasMany = [questions: SurveyQuestion]
static belongsTo = [user:User]
static constraints = {
}
}
class SurveyQuestion {
String question
static hasMany = [responses : SurveyQuestionResponse]
static belongsTo = [survey:Survey]
static constraints = {
}
}
When I create a Survey, I first see a screen like this :
I fill in the survey name, then click add a survey question, and see the next screen :
But it requires a survey being set, which hasn't yet completed.
Question : Do I have to create and save the survey first, then edit it and add survey questions (each of which individually need to be created and saved before I can create responses), or is there a way to add child objects as I'm creating the parent objects?
I want to use dynamic scaffolding so I don't have to create controllers and views manually.
The questions and answers are entirely independent, and will not be re-used across the hierarchy.
You should use command objects. This way you can comfortably add child elements while creating the parent. E.g.
class CreateSurveyCommand {
String surveyName
List<SurveyQuestion> surveyQuestions =
org.apache.commons.collections.list.LazyList.decorate(
new ArrayList(),
new org.apache.commons.collections.functors.InstantiateFactory(SurveyQuestion.class))
}
In the view (assuming index.gsp) you have something like:
<g:textField name="surveyName" value="${cmd?.question}" />
<g:each in="${cmd.surveyQuestions}" var="surveyQuestion" status="i">
<g:textField
name="surveyQuestions[i].question"
value="${cmd?.surveyQuestions[i].question}" />
</g:each>
<g:actionSubmit action="addQuestion"/>
Having an addQuestion action within your controller:
def addAction(CreateSurveyCommand cmd) {
cmd.surveyQuestions.add(new SurveyQuestion())
render(view:"index", model: [cmd: cmd])
}
Editing is another topic, but works the same way.
Have a look at this blog post:
http://blog.andresteingress.com/2012/06/29/groovy-2-0-love-for-grails-command-objects
Using that user interface you should create, save and add. A better approach is to create a master/detail user interface. You can see that approach here:
https://github.com/leadVisionary/Grails-Survey-Module
http://programmingitch.blogspot.com/2009/10/data-binding-for-one-to-many.html
http://omarello.com/2010/08/grails-one-to-many-dynamic-forms/
http://java.dzone.com/articles/creating-master-detail-forms
http://kapilpandit.wordpress.com/2009/02/25/complex_form_grails/
If you declare questions as a List in the Survey class then your views will be able to access them by index.
List questions
static hasMany = [questions: SurveyQuestion]
In your form GSP you can use something like this:
<g:textField
name="questions[0].question"
value="${surveyInstance?.questions?.size() > 0 ? surveyInstance?.questions[0]?.question : ''}"/>
The ternary for the value is a little crude but could easily be tucked away in your own tag.
If you really need to use dynamic scaffolding you can override individual views or the templates used to generate the view. Alternatively you could use the fields plugin to render the inputs for the questions property.
I've created a simple app & at that point everything appears to just work. I was expecting to have to write a PropertyEditor implementation to grow the list but it seems that Grails 2.1 will do this for you.
Reordering or removing questions would need more experimentation but updating the questions works, i.e. the question text is changed rather than a new SurveyQuestion instance being created.
If you are going to reuse the questions... maybe you shouldn't use a belongsTo =[survey:Survey]
Then if you don't have this relationship, you can create a template for creating the questions and add them to the question collection in survey object before saving it!

django admin foreignKey display troubles

I can't seem to find a solution for the following in the django docs.
So for example, i have a field in Class table called department that points to Department database (foreignKey). If I create a admin interface for Class table called ClassAdmin(admin.ModelAdmin). Then i create an entry for Department class. Now automatically, when i try to create a new Class entry, it will show a dropdown menu for entries in Department. The problem arises when i try to do that, it would show something along the lines of "Department Object" for each entry in the dropdown. I would like a way to define canonical names for each entry for department (Department.name is the field i would like to use).
Does anyone know how to do that?
Thanks a lot!
Implement the __str__ method in your Department model:
def __str__(self):
return self.name

MVC Partial Views, Models and more

I am pretty new to ASP.NET MVC and I am trying to get my head around some of the design concepts at the moment. One thing I am currently stuck on is how (best) to handle a situation such as that described below.
Suppose I have a page that needs to render a number of "sections". For example, on the left hand side there is a list that is data driven and then the selected item in the list displays a further list in another section on the page. For better understanding lets suggest the left hand list is a list of movie categories and the other list displays a list of movies that are contained within that category, along with the various movie details.
Now, I have some form of ORM such as Entity Framework, LINQ to SQL or whatever that maps the tblCategory and tblMovie database tables into Category and Movie entities respectively. These entities live in the MyMVCApp.Data.Entities namespace. I then use a repository pattern located in the MyMVCApp.Data namespace to encapsulate the queries (via LINQ) against these entities to return our model entities.
This is where my first question lies. Should the repository be returning view model entities or domain entities which are then extended to produce view model entities? In my naive mind I see the entities returned from the ORM as simply containers for the data with domain entities containing the business logic. So surely there should be an abstration here?
Anyway, back to my scenario. Now lets assume I wish to present the two sections described at the beginning of this. I am assuming that what should be happening here is my domain entity model would contain a list of categories and their associated movies. So something like a List each of which contains a List.
This model would have been populated somewhere. This is my second question. Say my assumption above is correct and it is simply data entities are returned from the ORM. Now I have a namespace/project called MyMVCApp.Core.Model (or the like) with some domain entities such as the Movie and Category entities mentioned in the previous paragraph. Do these entities have methods on them to retrieve the data from the ORM and populate themselves? Or does the repository retrieve these populated entity models? And another question on this part, if I have a Movie and Customer entity in my ORM is it acceptable to be having domain entities named the same?
Finally, I assume the controller now has this populated list of Category and Movie objects and passes it back to the view. I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each? So, it may be the IndexController which retrieves the populated CategoryMovies entity, passing this to the Categories partial view and the Movies partial view. I would then need to somehow determine the selected Category (quesrystring?) and display the appropriate list of Movies in that category within the view.
OK, so if anyone has got to this point in my ramblings I will take a deep bow. I hope I have explained my mixed up thoughts and questions in sufficient detail for someone to provide some kind of enlightenment.
Thanks for listening! :-)
Since you didn't mention it, I will assume you are new to DDD concepts. DDD compliments the "M" in MVC by placing logic where it belongs. And, I think a good amount could be applied here.
In strict DDD form, I would use your Movie example as an Aggregate Root (a DDD concept). Within Movie, you would have business logic (methods) that obtain the categories and related entities directly related to Movie (i.e. Categories-this-movie-belongs-in). This assumes the "category" list you want to display is a list of categories this movie is in.
public class Movie
{
private IList<Category> _categories;
public IList<Category> FetchCategories()
{
// you can lazy-load here, use Linq-to-Sql, etc.
return _categories;
}
public void AddCategory(Category c)
{
_categories.Add(c);
}
}
Of course, you can treat Categories as a Value Object (VO, a DDD concept) here if you don't have an identity on them.
Now, what gets more interesting is if you do want to keep an identity on your Categories, treating them as Aggregate Roots with multiple entities and relations to other VOs and alike. In this case, you would want to utilize the DDD concept of Services to combine the two aggregates into your requested Model you want to pass to your Controller. This allows you to create business rules around loading the categories.
public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
private IList<Category> _categories;
public IList<Category> Categories
{
get
{
return _categories;
}
internal set
{
_categories = value;
}
}
}
public class MovieCategoryService
{
public MovieCategory FetchMovieCategoryByMovieId(int id)
{
MovieCategory mc = _movieRepository.FetchMovie(id);
// do some logic here, some checks, etc
// to obtain your Categories list. Maybe querystring?
IList<Category> cats = ...;
mc.Categories = cats;
return mc;
}
}
The concept is that you now have logic in the domain layer, in this MovieCategoryService, to handle the complex creation of these relationships, or using Factories to create complex types as well.
This gives you a model you can pass around to different View and PartialViews.
The final step in your original post is how to get this into the View. I've been playing with the ViewModel approach to this issue. Creating ViewModels either dynamically, or as a class, and hanging all of the entities on this ViewModel. A recent StackOverflow question hits on this concept. ViewModel Best Practices
I've passed the Model directly into Views, and I am now trying this approach. It does clean things up, as your DOmain Model really should be disconnected from the "logic" on your page. I find myself thinking, "Dang it. I need to get this partialview populated based on this ID. Guess that means another method on the entity." Going the ViewModel approach removes the logic/thinking from the Domain Model, and puts it where it belong - in the Application/UI layer of where you are fine-tuning your view/partialview.
First of all, I think you should just get started with a simple project and try the various scenarios out you pictured in your long question :). There is nothing written in stone, you can use whatever architecture with datalayers and services or whatever, you like !
Or does the repository retrieve these populated entity models?
I would say yes. Your controller graps these from the service and gets them, populated and all and just moves them to the view in order to be displayed.
I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each?
And again i think you're on the right track ;).
It is a nice idea to give a view model entity to the view instead of the whole domain entity itself thereby providing the view only the required stuffs to work on
First of all return a List of Categories from your Domain, then construct a Movie view which takes the category name as a parameter something like this
- <Host>/Movies/Comedy
- <Host>/Movies/Horror
which would in turn display the movies which belongs to that particular category

Resources