Grails - Customizing the Scaffolding with extra templates - grails

I am implementing new project. I completed one use case, I likes to use scaffolding to generate all other uses cases. if i use generate-all it creates controller, services and views, But problem is, in my use case, there is 4 more types of classes <Domain>Search.groovy, <Domain>SearchBuilder.groovy, <Domain>TableDef.groovy, <Domain>DetailDef.groovy for every use case. So i have to create these four also with generate-all command.
how can i achieve with scaffolding.

A pracmatic approach could be to extend the set of templates (as you mentioned) and additionally to write your own gant scripts. Take a look at $GRAILS_HOME/scripts for some inspiration (i.e. 'CreateController.groovy').

Related

Where do all methods, attributes get wired into grails controller?

I'm looking at grails (2.2), and it's all beautiful and even magical, how it all works. I'm looking at a Controller class which is created with grails create-controller and out of the box it has many methods and properties available, like render(), redirect(), params, request and I presume it goes on and on.
where does all this get wired in? Where in the code/project/framework do I see that render() is made available as a method? And how is it implemented?
As a java developer I'm used to inheritance and code injection and reflection. And in javascript prototypes can do some black magic. But the XXController.groovy is just a standalone object. Is it the name (XXController) or the location (grails-app/controllers?) or is there some injection happening which the IDE can pick up?
Welcome to the wonderfull world of Grails,
Here you have a couple of links that may help you:
The Section of Controllers in the Web Layer docs.
And the docs of the render method. Check it out the "Quick reference" column at the right for more methods avaliable at the Controllers.
If you are wondering how that magic is done, Grails is an open source project, so as usual, go and serve yourself at Github (warning, it is quite large project).
Grails works on the top of Groovy, which is a Dynamic Language with a powerful support of meta programming. Tha is basically the trick of all the magic of Grails
Finally, Grails is a framework based on CoC (Convection over configuration), So the Controllers will be any class under the directory "grails-app/controllers" and with the suffix "Controller". (In the folder of controllers may be "commandObjects as well).
The integration with well-know ides is quite powerful as well, you should check it out
EDIT
You may also found how the render methods behaves here at github.
And more inyected stuff at the Controllers metaClass package
As of Grails 2.0+ it's implemented using an AST transformation - previously it was done by adding the methods to the Groovy MetaClass. The benefits of the new approach are that things will be a bit faster and use less memory.
GORM domain class methods now use this approach too (except for dynamic methods like findByFooAndBar which have to be added dynamically to the metaclass) and those have the benefit of being callable from Java since the AST adds the methods to the bytecode. This doesn't help controllers though since they're only called from Grails itself as the result of a web request.
For the gory details, ControllersApi is where the methods are, and they're mixed into each controller class by a combination of ControllerTransformer and the code in the doWithDynamicMethods closure in ControllersGrailsPlugin

changes to the domain class does not reflect changes to the view in grails app

I was wondering why the create page of my domain class won't reflect the changes that I did on my domain class. I tried adding some extra fields but it just won't appear on the UI.
I also tried changing the order the fields that are typed in on the static constraints = {} closure but to no avail and they still look the same order as before I did the change
Also tried grails clean, nothing happened
I am pretty sure I am in the right directory and I am using the development environment.
If you created your scaffolding by executing the generate-all command you are using static scaffolding. If you are using static scaffolding you will have to re-execute the generate-all command after modifying your domain class. Static scaffolding is meant as a template that you can modify for your needs. It is not meant to automatically change when your domain class does. Dynamic scaffolding will change when your domain class changes but offers less customization ability. In general static scaffolding is better for custom UI while dynamic scaffolding works well for things such as admin pages that most users won't see.

How does Grails resolve Controller name conflicts?

What is the recommended approach when an application Controller name conflicts with the name of a plugin's Controller?
I've seen these Grails JIRAs:
GRAILS-4240
GRAILS-1243
...and Burt Beckwith's replies to these two threads imply that the only recourse is to rename one of the Controllers (presumably the application Controller since hacking plugin code is not desirable)
How to use the package name to differentiate between classes in grails?
How to extend/override controller actions of plugins?
However, Burt's own spring-security-ui plugin advocates the exact approach of naming an application Controller the same as a plugin Controller - see spring-security-ui docs.
This approach actually seems to work in both development mode (grails run-app) and when the app is deployed as a WAR. So can this functionality be depended on? If so, what is the Controller conflict resolution rule? The grails docs do not make any mention of it. Perhasps Burt can share his insight?
Having a "plugin" architecture like grails' without even a basic namespacing facility to handle conflicts like this seems pretty broken to me...
The problem is that while you can use packages for any artifact, the convention for controllers is to remove the package and "Controller" to create URLs, e.g. PersonController -> /appname/person/action_name. So in effect everything gets flattened.
In 1.2 and more so in 1.3 things were changed so plugins are compiled separately from application code (and are compiled first) and this gives you the opportunity to replace a plugin artifact with the application's version. Since you shouldn't edit plugin code, this gives you the flexibility to extend or replace a plugin artifact just by using the same name.
I tend to use UrlMappings to get around stuff like this when there are two similarly named controllers. For example say you have an admin UserController that allows low-level CRUD actions and a regular UserController that users work with. I'd name the admin controller AdminUserController and map it to /admin/user/* and leave UserController as is. The admin GSPs will be in views/adminUser and the others will be in views/user so there's no conflict there. This has the added benefit of being able to easily secure - map /admin/** -> ROLE_ADMIN. The conventions are convenient, but this is a simple configuration step that solves this issue for me.
The good news is that GRAILS-1243 will definitely be implemented in 2.0 and possibly in 1.4. And the plugin that Kim Betti references in the comments of GRAILS-1243 looks interesting.

mvc rebuild strongly typed view

is there any way to re-build a strongly typed view when the model class has new fields added?
At present I have not modified the initial generated view so deleting and re-creating is not a problem.
When I start to customize it to my liking I will lose all changes and I was wondering if there was a good way to manage this?
Thanks
ASP.NET MVC offers two types of scaffolding, each with its own advantages:
The first kind of scaffolding is design-time scaffolding, which is done through the Add View dialog and T4 templates. The advantage of this is that the code is entirely generated and you can completely customize it. The disadvantage is that if you change your model you have to regenerate your view (by deleting it and adding back a new one).
The second kind of scaffolding is runtime scaffolding, which is done through the Html.EditorFor() and Html.DisplayFor() methods in your view. The advantage of this is that if your model changes then the scaffolding will be automatically generated at runtime. The disadvantage is that you cannot directly customize the rendering. You can, however, give this scaffolding many hints using DataAnnotations attributes such as [DisplayText], [UIHint], and so forth, so it is quite flexible - but it is not nearly as flexible as being able to 100% customize the rendering.
To customize the rendering of runtime scaffolding (editor templates and display templates) you can find more info on Brad Wilson's blog series.
You can manually add code to your view to reflect any changes in the model.
Default scafolding is there just to give you something.
One thing you might want to look at is t4 templates using wich mvc tooling generates your default views. google for it there are examples of how you can copy those to your project and modify to have mvc generate views you want instead of default ones.

Add a field to a Grails Domain Class?

I would like to add a field to an existing domain class. I do not want to lose my view files however as I know will happen if i run generate-all. Is there another way I can update the mapping etc?
I think this is a common concern.
This is not a direct solution to your problem, but this is what I do and works very well for me.
I never make direct modifications to the grails scaffolded artifacts (views and controllers)
I keep my production views/controllers separate from the scaffolded artifacts; through I use the scaffolded as the starting point of my application controllers and views.
If there are changes to the domain model, I re-generate the views and copy-paste (wherever possible) from scaffolded artifacts to hand-coded artifacts.
At some point, I either delete all the scaffolded artifacts from the app or just protect access to them.
Hope this helps.
There are a couple of ways to do this.
If you have not modified your generated views too much and are using version control, you could allow grails to overwrite your views and then merge the changes to the new templates with what is in version control.
If you have modified your generated views, you could just answer no to the prompt for overwriting the views. If you are only adding a new field, changing a field name or something simple like that, modifying the view templates should be pretty straight forward to do manually.
You would deal with any possible changes to the Controllers in the same way.
just declare it:
class MyDomain {
String newField;
}
Should be all you need to do.
Don't regenerate the views, just copy and paste another similar field to the one you are putting in the view(s) you want.

Resources