I am trying to write an attribute rule that will compare the field "FITTING_SIZE" in a Fitting (in this case a Water Tap) to the DIAMETER field in the Intersecting Water Service Line. Because the Tap also intersects with the Water Main, I'm using FilterBySubtypeCode to get only the Service Line, which has a SubType of 2. The following code always returns false and I'm not sure what I'm doing wrong. Currently I'm working in a file geodatabase in preparation for conversion to the Utility Network. Any assistance is appreciated.
var TapSize = Intersects((FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], false),2)), $feature) ;
if (TapSize == $feature.FITTING_SIZE) {
return true ;
} ELSE {
return false
}
Solved! Go to Solution.
After standing up some test data and playing around with the rules I was able to replicate that error, and this is what I came up with for a solution:
var intersecting = Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature);
if (Count(intersecting) == 0) return false
return First(intersecting).DIAMETER == $feature.FITTING_SIZE
This adds a "Count" check after the intersection and fails the rule if the feature isn't intersecting any lines. I assume the rule checker was feeding a null into the First which caused that error to pop-up. Wish the error message was better here but either way, that Count check seems to have fixed it. Note that this will fail if you move a fitting off a line, if that's too strict you can change line 2 to return true instead.
The result of Intersects is a feature set of all intersecting features, if you know there's only 1 intersecting feature you can use the First function to quickly grab a feature. You also have to grab a field from the feature for the comparison, and I think passing false for the geometry parameter in FeatureSetByName will cause problems. Therefore:
var tap = First(Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature));
return tap.tapSize == $feature.FITTING_SIZE
I haven't tested this but it should get you going in the right direction.
I tried the code you suggested, but the return statement does not allow a field name, which is what I assume you were calling "tapSize". It gave the error "Unexpected null".
I thought it might make the situation more clear if I change the name of the first variable to sLineDiam since what I am looking for in that statement is the diameter of the Service Line. So I tried this:
var sLineDiam = First(Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature));
return sLineDiam == $feature.FITTING_SIZE
Now it's returning an error on all taps within the extent.
Also, can you elaborate on the return statement? I thought a Validation Attribute Rule should return true for valid and false for invalid. Is that implied by the format of your return statement?
Thanks!
Almost there, we just need to extract the attribute value from the feature returned by First:
var sLineDiam = First(Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature));
return sLineDiam["DIAMETER"] == $feature.FITTING_SIZE
Just like JavaScript (and many other programming languages) the "==" operator compares both sides and returns true if they're equivalent or false otherwise. This means you can skip the if/else block as we're returning true/false directly.
If you still get errors, check to see if a Select by Location between the two feature classes works as intended in Pro, you might have features that appear to be coincident but actually aren't.
Thanks for the explanation of the return. I tried your suggestion but I'm back to getting the error "Invalid expression" if I try to include a field name (DIAMETER) in the return statement:
After standing up some test data and playing around with the rules I was able to replicate that error, and this is what I came up with for a solution:
var intersecting = Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature);
if (Count(intersecting) == 0) return false
return First(intersecting).DIAMETER == $feature.FITTING_SIZE
This adds a "Count" check after the intersection and fails the rule if the feature isn't intersecting any lines. I assume the rule checker was feeding a null into the First which caused that error to pop-up. Wish the error message was better here but either way, that Count check seems to have fixed it. Note that this will fail if you move a fitting off a line, if that's too strict you can change line 2 to return true instead.
David,
Thanks so much for your help. I was able to get it to work although at first I was confused with the lack of curly brackets in your code. I'm new to Arcade so maybe they're not always needed? I also needed to check to make sure the fitting was a Tap and not some other type, so I eventually ended up with this:
if($feature.FITTING_TYPE != "TAP") {
return true;
} else {
var intersecting = Intersects(FilterBySubtypeCode(FeatureSetByName($datastore, "WaterLine", ["DIAMETER"], true), 2), $feature);
if (Count(intersecting) == 0) {
return false
}
else {
return First(intersecting).DIAMETER == $feature.FITTING_SIZE
} }
Thanks again!