GRAILS: findALL() vs FindBy---(params.id) - grails

Greeting everyone,
I am trying to pass a parameters from a URL to a findAll() method.
LINE3 I use findAll() to define mouse.
LINE2 def house will bring in the parameter DELAWARE when I go to the page: http://localhost:8080/TestApp/home/county/DELAWARE
House will only show one instance instead of a list.. is there anyway to pass the url instead of ["DELAWARE"]? (please see line 3) thanks :)
def county() {
def house = Home.findByCounty(params.id) //sends only user related address to view
def mouse = Home.findAll("from Home h where h.county= ?", ["DELAWARE"]);
if (!house) {
response.sendError(404)
} else {
[house:house, mouse:mouse ]
}
}
Working Code +1 #Danilo
def county() {
def house = Home.findAllByCounty (params.id) //sends only county specified thru URL e.g. http://localhost:8080/TestAPP/home/county/DELAWARE
if (!house) {
response.sendError(404)
} else {
[house:house ]
}
}

findBy* will return at most one row, if you want to get all rows use findAllBy*
In order to understand how the URL will be used by Grails you have to have a look at conf/UrlMappings.groovy. You may find something like this:
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
}
}
this means that when you call TestApp/home/county/DELAWARE what Grails is trying to do is use the home controller (HomeController), invoking the county method (def county(){...}) and passing DELAWARE as id.
This should work correctly if inside county method of the HomeController you have:
def filteredInstances = Home.findAllByCounty(params.id)

Related

How to access a string from one method to another in one controller?

If we have one controller, let's call it document, that has two methods, one that uploads file and another that shows the uploaded file.
I would like to define a new string in the upload method that checks the size of the file and store a specific type name inside that string.
However I would like to access that string in another method which is the list method to be able to show it.
Here is my code:
Class DocumentController {
def list() {
//Here I would like to access that String to show it on the page
[fileSizeType: fileSizeType]
}
def upload {
//define the new String variable
String fileSizeType = ""
if(fileSize < 1000) {
fileSizeType = "type1.."
} else {
fileSizeType = "type2.."
}
}
}
In the gsp page I would like to access the string this way:
<td><g:link>\${fileSizeType}</g:link></td>
I am getting this error when I try the code above:
No such property: fileSizeType for class: file_down.DocumentController
You need to redirect to the list action while passing your argument in the params.
def upload() {
// simplify with ternary expression
def fileSizeType = (fileSize < 1000) ? "type1.." : "type2.."
redirect action:'list', params:[fileSizeType: fileSizeType]
}
// in your list action
def list() {
[fileSizeType: params.fileSizeType]
}

Save On My Domain Class Object Is Not Working.

I have a User class which has a List field namely pt. This field is not initialized when User register his account. But when user goes this controller action :
def updatePt() {
//performs some action
def user = User.get(springSecurityService.principal.id) //find the user
user.pt = []
//on certain conditions i put values into user.pt like this
user.pt << "E"
//at last I save it
user.save()
}
But using user/show action via scaffolding I found that pt field is not saved on users object. Where I'm making a mistake?
You have to provide a static mapping in the Users domain class so that Grails knows the field must be persisted:
class User {
static hasMany = [pt: String]
}
It's possible because of validation error. Try with
if (!user.save()) {
log.error('User not saved')
user.errors.each {
log.error('User error: $it')
}
}
PS or you can use println instead of log.error

Filtering filtered data

I'm new to grails and MVC so please bear with me.
I have some links on my GSP that do some static filtering. For instance, the example below returns only
those Request domain class instances with status Open. But I also want to be able to do some dynamic filtering on the same model (results in the code bellow).
Use case would be something like this: User sees all Request domain class instances in the table. He clicks on the link Open requests and gets only those Request instances that have status property with value Open. Than he sets dateFrom and dateTo using date picker control and clicks on the Filter button which calls the method/action that further filters data from the table. So it should return only those request that are opened and that are created within the specified period.
def openedRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
eq("status", "Open")
and {
'in'("productline",productlines)
}
}
render(view:'supportList', model:[requestInstanceList:results, requestInstanceTotal: results.totalCount])
}
EDIT
On my GSP I have few links that call controller actions which perform some domain class instances filtering. For example I have OpenedRequests, ClosedRequests, NewRequests. But I also have some textboxes, comboboxes, datePicker controls for additional filtering. I call the filterRequests action with a button.
def filterRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
if(params.fDateFrom && params.fDateTo){
def dateFrom = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateFrom_value)
def dateTo = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateTo_value)
between("dateCreated",dateFrom,dateTo)
}
if(params?.fStatus){
eq("status",params.fStatus)
}
if(params?.fCompany){
eq("company", params.fCompany)
}
and {'in'("productline",productlines)
}
if(params.sort != null && params.order != null){
order(params.sort, params.order)
}
}
render(view:'supportList', model:[requestInstanceList:results, requestInstanceTotal: results.totalCount])
}
I want to be able to filter Request instances with some of mentioned links and than if I set up some additional filters, for example dateFrom i dateTo with datePicker. I want those filters to be aware of previous filtering with link if there were any. What is the right way to do this?
You can use DetachedCriterias which where introduced with Grails 2.0.
A DetachedCriteria is independed from any session and can be reused easily:
def openRequests = new DetachedCriteria(Request).build {
eq("status", "Open")
and {
'in'("productline",productlines)
}
}
Then upon your next sub-filter request you can reuse the DetachedCriteria and perform a sub-query on it, like:
def results = openRequests.findByStartDateBetweenAndEndDateBetween(dateFrom, dateTo, dateFrom, dateTo)
Of course you have to remember somehow what the original query was (session, request param), to use the correct criteria as a basis for the sub-query.
(Disclaimer: I haven't yet tried detached criterias myself)
David suggested that I use Detached Criteria but I am using Grails 1.3.7 for my app. So, at the moment this isn't an option. I also thought of using database views and stored procedures but I wasn't sure how that will work with Grails (but that is something that I will definitely have to explore) and I wanted some results fast so I did something not very DRY. When I filter table with one of the mentioned links I save the name of the link/action in session and in filterRequest action (that does additional filtering) I check the session to see if there has been any previous 'link filtering' and if it were I apply those filters on the table with criteria, and after that I apply the filters that were manualy entered. I don't like it but that's all I came up with with my limited understanding of Grails. Below is my filterRequest action:
def filterRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
if(session.filter == "newRequests"){
and{
isNull("acceptedBy")
ne("status", "Closed")
}
}
if(session.filter == "openRequests"){
and{
ne("status",'Closed')
}
}
if(session.filter == "closedRequests"){
and{
eq("status", "Closed")
}
}
if(session.filter == "myRequests"){
and{
eq("acceptedBy", contact.realname)
}
}
if(params.fDateFrom && params.fDateTo){
def dateFrom = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateFrom_value)
def dateTo = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateTo_value)
and{
between("dateCreated",dateFrom,dateTo)
}
}
if(params?.fAcceptedBy){
and{
eq("acceptedBy", params.fAcceptedBy)
}
}
if(params?.fStartedBy){
and{
eq("startedBy", params.fStartedBy)
}
}
if(params?.fCompany){
and{
ilike("company", "%" + params.fCompany +"%")
}
}
and {'in'("productline",productlines)
}
if(params.sort != null && params.order != null){
order(params.sort, params.order)
}
}
}

Grains repetead code for actions in controllers

I have already posted this question, but i realised the aswer was not what i was looking for. Imagine this controller:
class exampleController{
def action1 = {
...
[lala: lala, lele: lele]}
...
}
def action15 = {
...
[lala: lala, lele: lele]
}
I want to be able to return in all the action in this controller the same params. Imagining this:
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
Is there any way of doing this, besides writing all the same code on all the actions? I have tried this method and it isnt working:
def action5 = {getModel()}
private getModel() {
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
}
}
It is not working because, and my thought is, he doest accept multiple [return1: aaa, return2: bbb]. Any suggestion please ? I have also tried filters like in here: Grails controllers repeated code for all actions
but i couldnt managed to make it work. I would apreciated a detailed explanaintion about any of the solutions if possible:p Thanks in advanced,
VA
So it's not the same model, but a model with a repeated part.
You should know that the return value is an ordinary Map.
So, return value can be constructed like return getCommonModel() + [book: currentBook] where getCommonModel() returns another Map.
If you want to return the same model from all your actions, this approach should work:
class ExampleController {
def action5 = {getModel()}
def action1 = {getModel()}
//etc.
private getModel() {
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
}
}
If you want to return the same model and render the same view from all your actions, you could return the same ModelAndView from each action, but then I would ask why do you need separate actions if they're all doing exactly the same thing?
I don't really understand your hypothesis
It is not working because, and my thought is, he doest accept multiple [return1: aaa, return2: bbb]
If your suggesting that getModel() can only return a model with a single entry, I find that very hard to believe. Can you elaborate a bit on this, or post some more information (e.g. stacktrace, unit test) that shows how/why it's not working?
Update
After reading your comments below I think I finally understand what you want to achieve, which is to append the model returned by getModel() (above) to the model returned by various other actions. Does this work:
class ExampleController {
def action5 = {
def action5Model = [foo: 'bar']
return addBookModel(action5Model)
}
def action1 = {
def action1Model = [foo2: 'bar2']
return addBookModel(action1Model)
}
//etc.
private Map addBookModel(Map model) {
def book = Book.findAllByIsbn(Isbn.get(1))
model.book = book
return model
}
}
This approach will only work when you want to add the book model within a single controller. If you want to add the book model in several controllers you can do this by:
putting addBookModel in an abstract class that the controllers extend
putting addBookModel in a class that is mixed-in with the controllers (using #Mixin)
putting addBookModel in a filter that is executed after the controller actions
If you are using exact same model in multiple pages. I would recommend you use a taglib for it.

Sending data to "View" from "Controller"

In my controller class have the following code
class MyController {
def flickrService
def index = {
def data = flickrService.search {
tags 'tag,tag2,tag3'
page 3
perPage 14 // Look ma!
}
[urls:data.urls,page:data.page,pages:data.pages]
}
}
I have also created an index.gsp file.
As I am new to groovy grails - i could not figure it out how to access data returned by flickrservice in the view. Can I just access "data" defined above in the index view or I need to set it in the controller before I can loop through the returned data? Any help would be highly appreciated. Thanks
Yes, now you can access data from the view, for example,in index.gsp:
<html><head>Test</head><body>${urls} <br/> ${page} </body></html>
Generally saying, grails return the last value in function by default, so if you want to access many data, you can do like this:
class MyController {
def flickrService
def index = {
def data = ...
def data1 = ...
def data2 = ...
// Here's the return result:
[view_data:data,view_data1:data1, view_data2:data2]
}
}
Then you can access ${view_data},${view_data1},${view_data2} in view.

Resources