i am trying to call a closure over each object of a class, and then displaying the objects which returned by the closure.
the closure is:
def activitiesPlanned={
cal.set(this.plannedStartDate)
def planDateMonth=cal.get(Calendar.MONTH)
def planDateYear=cal.get(Calendar.YEAR)
}
the call i made is:
def getActivitiesPlanned(int month,int year){
countActivitiesPlanned=ProgressData.each{it.activitiesPlanned.findAllWhere(planDateMonth:month,planDateYear:year).count()}
println countActivitiesPlanned
}
Domain Class //EDIT
package main
class ProgressData {
//String milestoneName
String taskId //Added later
String taskDescription
String taskCategory
Integer plannedHours
Integer actualHours
Date plannedStartDate
Date actualStartDate
Date plannedEndDate
Date actualEndDate
Integer stepsCreated=0
Integer stepsExecuted=0
String status //Originally Completed
String assignedTo
//String unplanned
String accepted //Added later
def ProgressData(){}
static constraints = {
//milestoneName(blank:false)
taskDescription(blank:false)
taskCategory(blank:false)
plannedHours(blank:false)
actualHours(blank:false)
id generator:"assigned",name:"taskId"
}
Calendar cal=Calendar.getInstance()
def activitiesPlanned={
cal.set(this.plannedStartDate)
def planDateMonth=cal.get(Calendar.MONTH)
def planDateYear=cal.get(Calendar.YEAR)
}
static hasMany=[defects:DefectData]
}
I am getting: "No such property: activitiesPlanned for class: main.ProgressData Possible solutions: activitiesPlanned". what issue may be there?
I think you don't want .each{} rather .sum{}
Example:
def listThing = [1,2,3]
def sumOfList = listThing.sum{it}
assert sumOfList == 6
Also ProgressData is a Domain Class so you can't use .each{} on it. You have to do ProgressData.list().each{ and by that I really mean ProgressData.list().sum{ for what I think you're trying to do.
Also, that activitiesPlanned closure doesn't return any activities...
Related
I am wondering if I can pass variable to be evaluated as String inside gstring evaluation.
simplest example will be some thing like
def var ='person.lName'
def value = "${var}"
println(value)
I am looking to get output the value of lastName in the person instance. As a last resort I can use reflection, but wondering there should be some thing simpler in groovy, that I am not aware of.
Can you try:
def var = Eval.me( 'new Date()' )
In place of the first line in your example.
The Eval class is documented here
edit
I am guessing (from your updated question) that you have a person variable, and then people are passing in a String like person.lName , and you want to return the lName property of that class?
Can you try something like this using GroovyShell?
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
GroovyShell shell = new GroovyShell( binding )
def result = shell.evaluate( commandString )
Or this, using direct string parsing and property access
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
// Split the command string into a list based on '.', and inject starting with null
def result = commandString.split( /\./ ).inject( null ) { curr, prop ->
// if curr is null, then return the property from the binding
// Otherwise try to get the given property from the curr object
curr?."$prop" ?: binding[ prop ]
}
Lets assume I have a domain class called Template that looks somewhat like this:
class Template{
String subject
...
}
I save an instance of this class:
Template t=new Template(subject:'Hello ${name}').save()
Now, I fetch this instance inside a method as follows:
def render(Long id){
String name='foo'
Template t= Template.get(id)
println t.subject
}
I want the "println t.subject" to be printed as "Hello foo". What I get is "Hello ${name}".
I want t.subject to dynamically replace the value of variable name - "foo" in place of ${name}.
Can this be achieved in groovy?
I cannot find any documentation of how to do this, or why this cannot be done.
Update:
I tried this on my GroovyConsole.
class Entity{
String name
}
class Template{
String name
String subject
}
String renderTemplate(Template template, Entity entity){
return template.subject
}
Entity e = new Entity(name:'product')
Template template=new Template(name:'emailTemplate',subject:'Product ${e.name}')
renderTemplate(template,e)
The Output I got was:
Result: Product product
class Template {
String subject
// ...
}
Template t = new Template(subject: 'Hello, ${name}').save()
Important: Use single quotes in 'Hello, ${name}' or you will get an error.
def render(Long id) {
String name = "world"
Template t = Template.get(id)
def engine = new groovy.text.GStringTemplateEngine()
def subject = engine
.createTemplate(t.subject)
.make(name: name)
println subject
}
There are a couple of things wrong with the code shown. You have this:
class Template{
String subject
...
}
Then you have this:
Template t=new Template(subject:"Hello ${name}").save()
The Groovy String assigned to the subject property will be evaluated as soon as you assign it to subject because subject is a String. The actual value will depend on the value of the name property that is in scope when that code executes.
Later you have this:
def render(Long id){
String name="foo"
Template t= Template.get(id)
println t.subject
}
It looks like you are wanting that local name property to be substituted into a Groovy String that has been assigned to t.subject, but that isn't how Groovy works. t.subject is not a Groovy String. It is a String.
Separate from that you comment that when you println t.subject that the output is "Hello ${name}". I don't think that is possible, but if that is what you are seeing, then I guess it is.
You can use a transient property to emulate the required behavior:
class Template{
String subject
String getSubjectPretty(){ "Hello $subject" }
static transients = ['subjectPretty']
}
Then you can use:
println Template.get(1).subjectPretty
I have domain classes A and B as follows:
class A {
String prop1
String prop2
B prop3
static embedded = ['prop3']
}
class B {
String prop4
String prop5
}
When I want to query like this:
def q = A.where { prop3.prop4 == 'bla' }
def list = q.list()
I get the following exception:
Cannot get property 'javaClass' on null object. Stacktrace follows:
on the "def q = A.where ..." line.
Any clue what's the problem? I've checked this:
http://grails.1312388.n4.nabble.com/GORM-embedded-object-issue-td1379137.html
but how to "just call them directly" is not quite clear to me. Any other way of querying the embedded objects in GORM?
I finally gave up on the where query and went with the DetachedCriteria approach. Gives me the same flexibility as the where queries, but works with embedded domain objects:
def criteria = new DetachedCriteria(A).build {
eq 'prop1', 'bla2'
}
criteria = criteria.build {
eq 'prop3.prop4', 'bla'
}
def list = criteria.list()
What do you get if you do (assuming B is in src/groovy)
def q = A.where { prop3 == new B(prop4: 'bla') }
def list = q.list()
Embedded components are persisted inside the main domain class (owner) itself. It can be accessed directly using any dynamic finder as you do directly on a domain object.
The above can also be represented in dynamic finders as:
A.findAllByProp3(new B(prop4: 'bla'))
I'm new to Grails development.
I have a domain class like this :
class DaySchedule {
Date Todaysdate
String startTime;
String endTime;
String task
int priority
boolean completed
static belongsTo = [ schedule : Schedule ]
}
I have bootstrapped with some test data's. Now I want to do a query, with following condition :
I need to pick each task (which are stored in bootstrap.groovy) which are belongs to a particularTodaysdate.
For example if I have these statements in my BootStrap.groovy :
//other codes
def daySchedule3 = new DaySchedule(Todaysdate:new Date(),
startTime:"6pm",endTime:"10pm",
task:"ReaD git...",completed:false)
def daySchedule4 = new DaySchedule(Todaysdate:new Date()+1,
startTime:"10am",endTime:"12pm",
task:"Read MySQL....",completed:false)
Now clearly the task, ReaD git... belongs to a day (which is today as I have passed new Date() into it).
To find these I came up with a partial solution like this:
def allTasks = DaySchedule.findAllByTaskIsNotNull()
def dates = allTasks.collect { it.Todaysdate }
def tasks = dates.collect {
def queryParameter = new DaySchedule(Todaysdate:it)
def todaysWork = DaySchedule.findAll(queryParameter)
todaysWork.task
}
I have a problem with this code. I couldn't use collectEntries method on the dates and tasks so that I convert it into map of a particular date(i.e dates) with values as tasks. (which is what I tried for!)
Now I'm left lone. I couldn't not able to find a way to guess for which dates the tasks belongs to.
Any other solutions for it?
Thanks in advance.
It sounds like you're trying to get a map with a key of the date, and a value of the task name, for all of the domain objects DaySchedule. You may want to try Collection.groupBy. For example:
def allTasks = DaySchedule.findAllByTaskIsNotNull()
def tasksByDate = [:] // start with empty map
tasksByDate.putAll(
allTasks.groupBy { task ->
// group by just the date portion, ignoring time
// clone since clearTime modifies original
task.todaysDate.clone().clearTime()
}.collect { date, daySchedule ->
// change from map of date -> daySchedule to map of date -> task
[date, daySchedule.task] as MapEntry
}
)
I think you have a design problem somewhere... it would be easier to have something like :
class Task {
Date startTime;
Date endTime;
String description
int priority
boolean completed
static belongsTo = [ schedule : Schedule ]
String toString() {
return "${description} : from ${startTime} to ${endTime}"
}
}
Then, you can list all the dates for which you have tasks in them like this :
java.text.DateFormat df = java.text.DateFormat.getDateInstance(DateFormat.LONG, Locale.US);
def days = Task.list().collect {
df.format(it.startTime);
}.unique()
So now the "days" variable contains an array of strings of unique days present in your database with tasks associated.
If you want to list the tasks by day, you can then do :
days.each { dayString ->
def date = df.parse(dayString)
def dayTasks = Task.findAllByStartTimeBetween(date, date+1)
println "Tasks for ${dayString}"
dayTasks.each {
println " - ${it}"
}
}
Public Function List_category() As Myobj
Dim query = From subcat In _dataContext.subcategories, _
cat In _dataContext.categories _
Where subcat.CategoryID = cat.CategoryID _
Select New Myobj() With { _
.SubcatId = subcat.SubCategoryID, _
.SubcatName = subcat.SubCategoryName, _
.CatId = cat.CategoryID, _
.CatName = cat.CategoryName _
}
return ?????????
End Function
Public Class Myobj
Private m_SubcatId As Integer
Private m_SubcatName As String
Private m_catId As Integer
Private m_catName As String
Public Property SubcatId() As Integer
Get
Return m_SubcatId
End Get
Private Set(ByVal value As Integer)
m_SubcatId = value
End Set
End Property
Public Property SubcatName() As String
Get
Return m_SubcatName
End Get
Private Set(ByVal value As String)
m_SubcatName = value
End Set
End Property
Public Property CatId() As Integer
Get
Return m_catId
End Get
Private Set(ByVal value As Integer)
m_catId = value
End Set
End Property
Public Property CatName() As String
Get
Return m_catName
End Get
Private Set(ByVal value As String)
m_catName = value
End Set
End Property
End Class
doesnt works!!!!
It Says 'Set' accessor of property 'SubcatName' is not accessible.
You can create a custom type and modify your select to instantiate that for the return. Take a look here: Linq To Sql return from function as IQueryable<T>
Compiler is just telling you that you have declared Private Set on SubcatName and yet ypou are trying to assing a value to it after New Myobj().
For a first run you can declare a POD class (plain old data - just public data, no methods or properties) and once you see it runnung you can go tweaking it, adding methods etc.
If it's really important that all properties are read-only you'll need to try making your querying method a static member of the same class.
Also, there is a way to return anonymous type and cast it back to equivalent anonymous type declared at the receiving side. Got to move on to C# though :-)
Example (read article):
// Method that returns anonymous type as object
object ReturnAnonymous()
{
return new { City="Prague", Name="Tomas" };
}
// Application entry-point
void Main()
{
// Get instance of anonymous type with 'City' and 'Name' properties
object o = ReturnAnonymous();
// This call to 'Cast' method converts first parameter (object) to the
// same type as the type of second parameter - which is in this case
// anonymous type with 'City' and 'Name' properties
var typed = Cast(o, new { City="", Name="" });
Console.WriteLine("Name={0}, City={1}", typed.Name, typed.City);
}
// Cast method - thanks to type inference when calling methods it
// is possible to cast object to type without knowing the type name
T Cast<T>(object obj, T type)
{
return (T)obj;
}