Open Daniel-Dragon opened 4 years ago
I'm not entirely sure I understand your first bullet point -- Can you provide an example of that usage? The most common usage of fflib_SObjectSelector
is to subclass it for your own object and define the list of field sets you want to query by overriding the virtual getSObjectFieldSetList()
The purpose for having multiple Field Sets usually becomes evident if you need multiple Selectors -- i.e. a 'get me the kitchen sink' Selector that enumerates all fields and perhaps a more narrow Selector where heap size or some other consideration (FLS) makes it convoluted to use a single kitchen sink Selector.
Please keep in mind that this could be a serious misunderstanding on my part. I'm slowly piecing together how this is supposed to work and reading the book! So my assumption is that whenever we need the Selector "injected" anywhere we want to use Application.Selector.newInstance, this will allow us to inject a mock when testing, and allow us to swap out implementations if they change.
So with that assumption, what I am saying is If I'm using the Application static class to get the selector right? Say Account object so I have an AccountsSelector class, and it's registered in my Application class.
So now I'm supposed to use Application.Selector.newInstance(Account.SObjectType) when I want to inject it? (If that part is wrong then my whole question is wrong) What if I want to inject the "Kitchen Sink" this time?
All of that is right on, and as long as the "Kitchen Sink" implements fflib_ISObjectSelector
, you'll be fine.
Additionally the selector implementation could contain a static newInstance()
method that calls Application for you, so the usage might look like:
List<KitchenSink__c> sinkList = KitchenSinkSelector.newInstance().selectSinksByVolume(...);
See the sample usage project, where the AccountsSelector [1] has it.
Welcome to AEP, and I look forward to hearing about your experiences and perhaps some suggestions.
Ah this is perfect thank you! I knew I saw this somewhere. OK, so that leaves the last point of question still open I think which is the FieldSet itself.
So I pulled the example here from Andrew Fawcett's book. The snippet below is extending fflib_SObjectSelector and is intended to be extended further with an actual selector class to give context.
public abstract class ApplicationSelector extends fflib_SObjectSelector {
public ApplicationSelector() {
this(false);
}
public ApplicationSelector(Boolean includeFieldSetFields) {
// Disable the default base class read security checking
// in preference to explicit checking elsewhere
this(includeFieldSetFields, false, false);
}
public ApplicationSelector(
Boolean includeFieldSetFields,
Boolean enforceCRUD,
Boolean enforceFLS) {
// Disable sorting of selected fields to aid debugging
// (performance optimisation)
super(includeFieldSetFields, enforceCRUD, enforceFLS, false);
}
}
These constructors seem to give us the flexibility to includeFieldSetFields, enforceCRUD, enforceFLS, ETC Right? How can we leverage these constructors (To get the kitchen sink implementation by saying includeFieldSetField = true) when using an implementation of the class though, how can I call one of these constructors? Without explicitly defining the class that I'm creating of course! Because if I do that then I lose the ability to Mock.
G'day @Dan-Baba
"These constructors seem to give us the flexibility to includeFieldSetFields, enforceCRUD, enforceFLS, ETC Right? "
"How can we leverage these constructors (To get the kitchen sink implementation by saying includeFieldSetField = true) when using an implementation of the class though how can I call one of these constructors? Without explicitly defining the class that I'm creating of course! Because if I do that then I lose the ability to Mock."
Application.cls
starting at line 52. This is a typical example of the Application class setup in a non-DX environment. The AT4DX version of the Application.cls
starting at line 40 is what you would use if you have a DX project with multiple second generation packages.fflib_SObjectSelector
. The ApplicationSObjectSelector
does enable field sets as it is part of the AT4DX fieldset injection functionality, so that might help you.setMock
methods to help you take advantage of that functionality. Look in the fflib-apex-common-samplecode and the at4dx-samplecode projects for examples of its usage.Trust this helps.
Daniel-Dragon did you ever determine how to do this? I am in a similar boat as you - as of now, my solution is to define overloaded newInstance methods in the selector:
public static ChangeRequestsSelector newInstance() {
return newInstance(false, false);
}
public static ChangeRequestsSelector newInstance(Boolean runInSystemMode) {
return newInstance(runInSystemMode, false);
}
public static ChangeRequestsSelector newInstance(Boolean runInSystemMode, Boolean includeFieldSetFields) {
ChangeRequestsSelector selector = (ChangeRequestsSelector) Application.selector.newInstance(Change_Request__c.SobjectType);
selector.setDataAccess(runInSystemMode ? fflib_SObjectSelector.DataAccess.SYSTEM_MODE : fflib_SObjectSelector.DataAccess.USER_MODE);
if (includeFieldSetFields) {
selector.includeFieldSetFields();
}
return selector;
}
Hello, I have more of a discussion question regarding how to enable FieldSets to be more flexible.