last day (42 days later) » 

5:09 PM
would it be possible to email off this thread? I have taken the advice you have given me but I am not sure if it is possible to compare two different Objects with two different fields. Every which way I try it, I get back an error that Date_Activity_Logged__c is an invalid identifier or type. I am able to compare one Object with two different fields but am struggling with two different Objects. — Olivia 50 secs ago
 
Hi there!
 
I didn't know this was possible. I truly appreciate all of you help.
 
sure thing
 
So as a little background-I am basically flying solo over here (I am the only SF dev in my company) and I am trying to learn APEX as fast as possible.
 
5:12 PM
fun times
 
Anyways, my confusion with the Comparable class comes with the second object
 
Ah, the link to the question didn't quite work
http://salesforce.stackexchange.com/questions/132953/descending-table-with-two-objects
1
Q: Descending Table With Two Objects

OliviaI have a table that lists out two different objects in descending order. The issue is that the list is returning all of one object and then all of the second object. It is still in one table but the dates will restart half way down the list. How do I get all of the objects to list together in one...

so did you implement the wrapper verbatim?
what are you passing in the field parameter?
 
yes
global class DateSorter implements Comparable
{
final SObject task;
final Datetime value;

DateSorter(SObject task, SObjectField Date_Activity_Logged__c)
{
this.task = task;
this.value = (Datetime)task.get(value);
}
public Integer compareTo(Object instance)
{
DateSorter that = (DateSorter)instance;
if (this.value == that.value) return 0; // extremely unlikely
return (this.value < that.value) ? 1 : -1;
}
}
I have tried a number of different variations
So my understanding is that: we created a class that implements comparable, I create a method compareTo that will compare one object and one field to another object and another field
the field in Task is a custom field "Date_Activity_Logged__c"
 
no that's not verbatim
and it's not how you pass fields
 
and the field in note is a standard field "CreatedDate
 
5:16 PM
you should specify the parameter value in your method definition
 
I tried literally exactly how you wrote it but I assumed i needed to customize it to accept my fields
 
you need to pass the fields in
change it back to DateSorter(SObject task, SObjectField field)
then when you instantiate
you pass in your record and the field token
which you can get by doing
Task.Date_Activity_Logged__c
or Note.CreatedDate
you can also just use strings and pass in the api name as a string (everything after the .)
so you would do new DateSorter(taskRecord, Task.Date_Activity_Logged__c)
or new DateSorter(noteRecord, Note.CreatedDate)
does that make sense?
 
yes...
I am wrapping my head around it
 
gotta make you do some of the work :P
step 1: instantiate new List<DateSorter>
step 2: iterate Task records and add new DateSorter(record, Task.Date_Activity_Logged__c)
step 3: iterate Note records and add new DateSorter(record, Note.CreatedDate)
step 4: sort your List<DateSorter>
step 5: iterate your List<DateSorter> and pull the records out into a List<SObject>
 
I appreciate you not just giving me the answer! I prefer to actually learn so I dont have to keep asking questions down the line.
thank you for these steps. so something I was getting caught on, Step 2- would I bring in the SOQL query to iterate through the task records?
I have seen other threads that the -1, 0, 1 creates the list for you
also, how did you get so good at SF dev?!
 
5:29 PM
eh?
i don't understand your Q
i got good at it via exacting pedantry and ocd lol
mostly self taught tbh
also just read everything sfdcfox writes
and cropredy
they both have pretty good blogs
 
Would I have to put the list of tasks and notes in my new List or does the compareTo method create the list for me?
public class DateSorter implements Comparable
{
final SObject record;
final Datetime value;

DateSorter(SObject record, SObjectField field)
{
this.record = record;
this.value = (Datetime)record.get(value);
}

public Integer compareTo(Object instance)
{
DateSorter that = (DateSorter)instance;
if (this.value == that.value) return 0; // extremely unlikely
return (this.value < that.value) ? 1 : -1;
}

new DateSorter(taskRecord, Task.Date_Activity_Logged__c){

}

new List<DateSorter> tasksAndNotes(){
like so^
 
don't define any new constructors
don't modify the wrapper class at all
use it verbatim
here's a more explicit flow:
 
okay
 
List<DateSorter> wrappers = new List<DateSorter>();
for (Task record : [/*query*/]) wrappers.add(new DateSorter(record, Task. Date_Activity_Logged__c);
for (Note record : [/*query*/]) wrappers.add(new DateSorter(record, Note.CreatedDate);
wrappers.sort()
List<SObject> sortedRecords = new List<SObject>();
for (DateSorter wrapper : wrappers) sortedRecords.add(wrapper.record);
I missed the closing parens on wrappers.add(...)
oops
is that more clear how to add wrappers to the list?
 
okay so I would use the query...this is making more sense. I would sort it in ascending order, and then I would create a new list, loop through the queried list and add the DateTime 'record' to the new list
 
5:43 PM
um
 
lol am I way off? ugh!
why is this so hard
List<DateSorter> wrappers = new List<DateSorter>();
for (Task record : [Select CreatedById, Subject, Description, CreatedDate, Date_Activity_Logged__c From Task WHERE Status = 'Completed' AND
         (AccountId = :actId OR WhatId = :actId OR WhoId = :actId)]) wrappers.add(new DateSorter(record, Task. Date_Activity_Logged__c));
for (Note record : [Select CreatedById, Title, Body, CreatedDate From Note WHERE ParentId =: actId]) wrappers.add(new DateSorter(record, Note.CreatedDate));
wrappers.sort()
^^this is putting the list of tasks and notes into wrappers
and then I call .sort on it
 
right
 
which will put it in ascending order
then I create a new list: List<SObject> sortedRecords = new List<SObject>();
and inside of this list I loop through the old list "wrapper" and add the wrapper record to this new list
 
i think it's written for descending order
 
for (DateSorter wrapper : wrappers) sortedRecords.add(wrapper.record);
 
5:45 PM
correct
 
oh, I thought .sort was always ascending
 
no you are defining your own sort algorithm with the Comparable interface...
you can define it however you want
you could define it to random sort
or whatever floats your boat
 
oh interesting. okay okay
so now I have this new list, of tasks and notes 'records' which is a Datetime value.
and the compareTo method automatically updates the position of the date in the list
correct?
 
no...the wrapper has two properties
one of them is `Datetime`, so you can sort
one of them is `SObject`, so you can put the results into a `List<SObject>` eventually
records are of type SObject
 
you're right it does have both
so when I look at sortedRecords, what I see is a list of only CreatedDates and Date_Activity_Logged__c...I can sort this no problem. my question is, how will it relate back to the original list?
or is it when I bring over the CreatedDate and Date_Activity_Logged__c, the entire task and the entire note comes along with it?
 
5:57 PM
sortedRecords should not be List<Datetime>, but rather List<SObject>...
the value property holds the data in that filed
field*
the record property stores the entire record
 
ohhhhhhhhhh
okay so in my sortedRecods list is the entire record WITH the Datetimes organized. I would now need to save this into a new list.
 
no it is the new list
 
okay, so it is fine just as it.
is*
 
this is what I have...
public class DateSorter implements Comparable
{
final SObject record;
final Datetime value;
String actId;

DateSorter(SObject record, SObjectField field)
{
this.record = record;
this.value = (Datetime)record.get(value);
}

public Integer compareTo(Object instance)
{
DateSorter that = (DateSorter)instance;
if (this.value == that.value) return 0;
return (this.value < that.value) ? 1 : -1;
}

List<DateSorter> wrappers = new List<DateSorter>();
{for (Task record : [Select CreatedById, Subject, Description, CreatedDate, Date_Activity_Logged__c From Task WHERE Status = 'Completed' AND
this makes sense to me
but I have two red flags:
I am getting an error message: Method does not exist or incorrect signature: [SObject].get(Datetime)
and when I want to pass in my actId, I will have to use
public noteandtask_controller(ApexPages.StandardController stdController)
{
actId = stdController.getId();

in order to pass in the actId
 
6:06 PM
don't call record.get(value)...it's supposed to be record.get(field)
my bad
gah std is such a poor abbreviation choice
 
how will I pass in APEX.StandardController into the params of the controller when the controller already has params in it?
 
much better taste to simply name the property controller
 
haha
WOOPS
 
didn't even realize
I will be changing that
oh wait...can I do something like this?
public class DateSorter implements Comparable
{
final SObject record;
final Datetime value;
String actId;

public DateSorter(ApexPages.StandardController stdController)
{
actId = stdController.getId();
}

DateSorter(SObject record, SObjectField field)
{
this.record = record;
this.value = (Datetime)record.get(field);
}

public Integer compareTo(Object instance)
{
DateSorter that = (DateSorter)instance;
if (this.value == that.value) return 0;
return (this.value < that.value) ? 1 : -1;
}

List<DateSorter> wrappers = new List<DateSorter>();
 
6:09 PM
right
get(field)
 
okay I am going to try it in action. let's see what happens
 
6:34 PM
hum I can't save it. Have you ever run into this error message: duplicate value found: <unknown> duplicates value on record with id: <unknown>
google is saying that it might have something to do with history tracking
and because I cant save, I cant connect my VF page to the controller
 
um what ide are you using? just dev console?
 
yes
 
try changing your workspace
usually that helps
 
nope still giving me the error
 
try editing it through the ui
setup>develop>apex classes
it's a metadata issue
sounds like
 
6:50 PM
got it
 
7:02 PM
you know how you have a query inside of the for loop? isn't there a limit on returned results when you do this?
 
that's not a query in a for loop
it's a for loop query
:P
it's a SOQL For Loop*
 
oh okay
I am getting back a "too many SOQL queries: 101" error which is why I thought it was a limit on the loop results
 
it's pretty hard to read your code in the chat format
maybe create a gist?
 
public or secret?
 
your call
don't have your controller implement comparable...
use an inner class
also you're using some extra curly brackets ({})
commented on your gist
you've got a recursive issue
you have an object that has a property that is a list of itself
that's why you use a wrapper class instead
i think...i'm not sure why you're hitting that limit but the structure is definitely weird. I think it's because the extra brackets are creating an initialization block
yeah it's definitely because you're (accidentally, I assume) using an initialization block for each wrapper (DateSorter)
splitting them out and correcting the location of the initialization (into the controller constructor) should fix it
 
8:22 PM
so I corrected the location of the initialization
I update the gist
and I changed the initialization block for each wrapper
but I am not sure if I am going about it correctly. I am getting an "Constructor not defined: [noteandtask_controller].<Constructor>(Task, Schema.SObjectField)" They way I view it is I need to make each wrapper consistent with the class name
right?
 
9:13 PM
Don't call the wrapper class a controller, it's confusing you
and it's not really true
in your actual controller constructor, you are trying to add to a list of constructors
a list of controllers*
instead of a list of comparable
it looks like revision 2 should have worked
 
I get an error on the query
"Constructor not defined: [noteandtask_controller].<Constructor>(Task, Schema.SObjectField)"
 
yeah because you need to construct the wrapper class (that implements comparable)
not the top level class
 
 
1 hour later…
10:33 PM
okay I think I got it!
the only error I am getting now is in my VF page: "Unknown property 'noteandtask_controller.myController.Id'"
I updated gist
 

  last day (42 days later) »