Thanks Aaron, your suggestion is working well. It is analogous to a "git
rebase” ;-) I feel better with this code.
I did find that the technique did not work for to-many relationships, but added
a bit of code towards the end of the method to refresh the to-many
relationships using Wonder:
/**
* Core method to refresh properties selectively with data from the
database. The
* properties can be attributes, to-one or to-many relationships.
*/
public void refreshProperties(NSArray<String> keys) {
NSDictionary<String, Object> changes = changesFromCommittedSnapshot();
// Discard changes to the properties that we're about to refresh if any
NSMutableDictionary<String, Object> changesToKeepAfterRefresh =
changes.mutableClone();
changesToKeepAfterRefresh.removeObjectsForKeys(keys);
// Now fetch the receiver refreshing it with changes from database
EOEntity entity = entity();
EOFetchSpecification fs = new EOFetchSpecification(entity.name(),
primaryKeyQualifier(), null);
fs.setRefreshesRefetchedObjects(true);
editingContext().objectsWithFetchSpecification(fs);
// Now re-apply the changes we want to keep
if (changesToKeepAfterRefresh.count() > 0) {
takeValuesFromDictionary(changesToKeepAfterRefresh);
}
// The above will not refresh to-many relationships so do something a
bit
// more drastic to refresh the to-many relationships.
for (String key : keys) {
EORelationship relationship = entity.relationshipNamed(key);
if (relationship.isToMany()) {
ERXEOControlUtilities.clearSnapshotForRelationshipNamed(this,
key);
}
}
}
And some convenient methods to go with it too:
/**
* Convenience method to refresh properties selectively with data from the
database.
* The properties can be attributes, to-one or to-many relationships.
*/
public void refreshProperties(String... keys) {
NSArray<String> keysArray = new NSArray<String>(keys);
refreshProperties(keysArray);
}
/**
* Convenience method to refresh properties selectively with data from the
database.
* The properties can be attributes, to-one or to-many relationships.
*/
public void refreshProperties(ERXKey<?>... erxKeys) {
NSMutableArray<String> keys = new
NSMutableArray<String>(erxKeys.length);
for (ERXKey<?> erxKey : erxKeys) {
keys.add(erxKey.key());
}
refreshProperties(keys);
}
> On Sep 3, 2016, at 4:45 PM, Aaron Rosenzweig <[email protected]>
> wrote:
>
> Hi Ricardo,
>
> That’s some clever WO-ninja magic you got going on there. I’ve never replaced
> the original snapshot of an EO before.
>
> If it works, great - I won’t knock it but I’d be scared without flexing it
> (using it a bunch).
>
> Another idea…
>
> 1) hold onto the “changesFromCommittedSnapshot” so you can refer to it.
>
> 2) in your fetchSpec make “setRefereshesRefetchedObjects()” to true - so when
> you go round trip you’ll update the EO.
>
> 3) reapply your changes from the committed snapshot.
>
> Cheers,
> AARON ROSENZWEIG / Chat 'n Bike <http://www.chatnbike.com/>
> e: [email protected] <mailto:[email protected]> t: (301) 956-2319
>
>
>
>> On Sep 3, 2016, at 9:34 AM, Ricardo Parada <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> Hi all,
>>
>> I have a need to refresh the to-one relationship of an object, so that if
>> someone in another app or perhaps in a different EOF stack within the same
>> app has updated the to-one to point to a different object then I want my
>> EO’s to one to point to the correct EO. I do not want to invalidate the
>> source EO or refetch it because it may have edits in progress.
>>
>> I searched in Wonder but I was not able to find anything that does this. I
>> came up with the code below last night and it seems to work well so far.
>>
>> Since this is an advanced EOF topic I thought I should share it to see if
>> anybody wants to code review it, play with it and provide comments on
>> correctness / recommendations / feedback.
>>
>> This code uses a primaryKeyQualifier() method in my EO which is practically
>> the same as the identityQualifier() concept discussed by Aaron Rosenzweig in
>> an email thread in May of this year.
>>
>> Thanks in advance for any help.
>>
>>
>> @SuppressWarnings("rawtypes")
>> public void refreshToOneRelationshipWithKey(String toOneName) {
>> EOEditingContext ec = editingContext();
>> EOEntity entity = entity();
>> EORelationship toOne = entity.relationshipNamed(toOneName);
>> String foreignKeyName = toOne.sourceAttributes().lastObject().name();
>> EOFetchSpecification fs = new EOFetchSpecification(entity.name(),
>> primaryKeyQualifier(), null);
>> fs.setRawRowKeyPaths(new NSArray<String>(foreignKeyName));
>> @SuppressWarnings("unchecked")
>> NSDictionary<String,Object> dict = (NSDictionary<String,Object>)
>> ec.objectsWithFetchSpecification(fs).lastObject();
>> Object newForeignKeyValue = dict.allValues().lastObject();
>> EOGlobalID gid = globalID();
>> EOModel model = entity.model();
>> EODatabaseContext dbc =
>> EODatabaseContext.registeredDatabaseContextForModel(model, ec);
>> EODatabase database = dbc.database();
>> EOObjectStoreCoordinator osc = (EOObjectStoreCoordinator)
>> ec.rootObjectStore();
>> osc.lock();
>> try {
>> NSDictionary snapshot = database.snapshotForGlobalID(gid);
>> Object currentForeignKeyValue =
>> snapshot.objectForKey(foreignKeyName);
>> // We don't need to check for null as currentForeignKeyValue and
>> newForeignKeyValue
>> // use NSKeyValueCoding.NullValue to represent null.
>> if (currentForeignKeyValue.equals(newForeignKeyValue) == false) {
>> NSMutableDictionary newSnapshot = snapshot.mutableClone();
>> newSnapshot.takeValueForKey(newForeignKeyValue,
>> foreignKeyName);
>>
>> database.recordSnapshotForGlobalID(newSnapshot.immutableClone(), gid);
>> Object toOneValue = NSKeyValueCoding.NullValue;
>> if (newForeignKeyValue != NSKeyValueCoding.NullValue) {
>> EOKeyGlobalID toOneGID =
>> ERXEOGlobalIDUtilities.createGlobalID(toOne.destinationEntity().name(), new
>> Object[] {newForeignKeyValue});
>> toOneValue = ec.faultForGlobalID(toOneGID, ec);
>> }
>> // Update __originalSnapshot() and EO so that
>> changesFromCommittedSnapshot()
>> // does not think that the object has changed.
>> NSDictionary originalSnapshot = __originalSnapshot();
>> NSMutableDictionary newOriginalSnapshot =
>> originalSnapshot.mutableClone();
>> newOriginalSnapshot.setObjectForKey(toOneValue, toOneName);
>> __setOriginalSnapshot(newOriginalSnapshot.immutableClone());
>> if (toOneValue == NSKeyValueCoding.NullValue) {
>> takeStoredValueForKey(null, toOneName);
>> } else {
>> takeStoredValueForKey(toOneValue, toOneName);
>> }
>> }
>> } finally {
>> osc.unlock();
>> }
>> }
>>
>> public EOQualifier primaryKeyQualifier() {
>> NSDictionary<String, Object> pkDict = primaryKeyDictionary(false /*
>> inTransaction */);
>> EOEntity entity = entity();
>> return entity.qualifierForPrimaryKey(pkDict);
>> }
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Webobjects-dev mailing list ([email protected]
>> <mailto:[email protected]>)
>> Help/Unsubscribe/Update your Subscription:
>> https://lists.apple.com/mailman/options/webobjects-dev/aaron%40chatnbike.com
>> <https://lists.apple.com/mailman/options/webobjects-dev/aaron%40chatnbike.com>
>>
>> This email sent to [email protected]
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com
This email sent to [email protected]