Enable Automatic Lightweight Migration of Core Data on NSPersistentDocument - macos

ALM is great. But I can't get it to work on a project that uses Core Data with NSDocument. It seems that ALM is disabled by default.
Fine. For any normal project, you'd add the two appropriate options to the dictionary in this line:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
...but that line doesn't exist when using CD with NSD (NSPersistentDocument hides the details and I can't see how you can modify them).
The following method seems to offer hope:
configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:
...some people on mailing lists (from 4+ years ago) report success overriding that method, altering the options dictionary, and then re-invoking it on "super". That didn't work for me, sadly. I would advise trying that first if you have similar problems - then come back here if it still doesn't work :)

Making a new Cored-Data-with-NSDocument project from scratch, I tried the approach that didn't work originally, and it worked fine this time:
-(BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newOptions = [NSMutableDictionary dictionaryWithDictionary:storeOptions];
[newOptions setValue:#"YES" forKey:NSMigratePersistentStoresAutomaticallyOption];
[newOptions setValue:#"TRUE" forKey:NSInferMappingModelAutomaticallyOption];
return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newOptions error:error];
}

NB: I suspect the root cause of my problems is that Xcode4 is incorrectly updating the private hashes it uses instead of version numbers to track a data-model version. Probably I accidentally added something, then deleted it, and it changed the hash - my original model was so very simple it was easy to compare by eye, and there were no differences.
Also, more generally, the problem is that Xcode4 still doesn't handle CoreData projects properly - it creates CoreData models as "versioned" by default (big improvement from Xcode3, which was doomed to always create useless models), but it still doesn't do any handling of changes in the model - you must manually remember to update the version BEFORE you save any changes (or else all your project migration will fail, forever, with no way out).
Also, I couldn't find any "correct" solution once things go wrong - just too many missing pieces from Apple's Core Data lib. Basically: NSPersistentDocument is incomplete, unsupported, so far as I can tell.
In the end, I went with the following BRUTAL workaround: instructed everyone with old versions to manually edit the CoreData stores to claim they are running the current version.
This works 100%, because unlike CoreData, my app is written to intelligently correct any obvious missing data on import. It's trivial, but CoreData doesn't allow you to say "yes, I've done this. It's OK. Go ahead and open the file!"
in old version: "save as XML"
gave them the new header to copy/paste into top of file. NB: Apple uses hashes instead of version numbers, which makes this look scary, even though it isn't. I don't understand why Apple is ignoring their own version system and using hashes instead?
in new version: open the updated file
in new version: "save"
...and because I'm overriding the NSManagedObject method:
-awakeFromInsert
and fixing any incorrect/missing data, the steps 3 and 4 above "automagically" update the data.
I know that the "correct" way would have been to create a mapping model, but it's massive overkill for most situations ... and Apple was refusing to load the old data in the first place. So, Core Data was just refusing to even allow me to correct the data - even though my code was happily doing so.
(all old projects have imported and exported correctly - no problems)
IMHO: CoreData really needs some re-design on Apple's end to fix all the edge-cases they didn't think about first time around.
NB: quick warning: make sure you DON'T change any CoreData variables inside awakeFromFetch - Apple temporarily disables change-tracking before calling that method (which is kind of laughable - it makes the method incompatible with the behaviour of all other "awakeFrom*" methods).
Apple's advice: inside awakeFromFetch, decide what you're going to change, then package it up and use something like this:
[self performSelector:#selector(myAwakeFromFetchFixItemX:) withObject:X afterDelay:0.01];
...just thought I'd add that for anyone trying this - otherwise your import will work fine, but your export will silently fail to include the fixed data!

Related

How to Get FHIR Photo for Patient from a URL

Consider the FHIR Patient data at http://spark.furore.com/fhir/Patient/f201.
How can I get the photo object referenced therein at URL "binary/#f006"??
I would have thought an HTTP GET on http://spark.furore.com/fhir/binary/#f006 would have done it, but alas...
the data there is wrong. Your conversion to the get was correct, but you ended up with a wrong URL because the reference is wrong in the first place.
It should say: url="Binary/f006" which would equate to a get of http://spark.furore.com/fhir/Binary/f006. That doesn't work either, which is another error in the way things are defined.
See http://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=6107 for follow ups
Yes, this reference is outdated, and we are not distributing Binaries currently as part of the examples in the FHIR specification. Our server Spark loads the examples from the specification when we initialize the database, hence the images are not there.
For now, I have uploaded the correct image to Binary/f006 and have updated the link in Patient/f201, so things should work now. When we re-initialize the database (we don't do this often), these changes will be reversed, but a simple PUT to Binary/f006 and an update of Patient/f201 will fix this of course.

Kohana ORM Caching/Caching design approach

This questions is related to Kohana ORM AND Caching module. I use version 3.2 if it matters. I tried to research trust me, but I really couldn't find some good answer... so here it is:
What are the correct ways to use ORM::cached() and ORM::serialize() and ORM::$reload_on_wakeup?
I've seen many 2-line code examples but never anything really solid on the userguide/api...
What is the difference between enabling Cache module and 'caching' => true in Kohana::init?
Anyone has any recommended approach for the following specific situations? I have a catalogue page that upon profiling, I realized two very expensive actions:
I queried database each time for a currency model for each item, when the currency information can really be reused.
I queried database each time for each item's inventory item, this is an expensive query, which I wish I can cache until inventory level changes.
References that I found but couldn't answer fully my questions:
http://forum.kohanaframework.org/discussion/1782/tip-for-caching-orm-objects/p1
http://forum.kohanaframework.org/discussion/10600/does-kohana-orm-and-cache-work-together/p1
Just found your question, maybe too late, but maybe is useful to others:
cached, will force the Query builder to cache the DB query. It uses the KOhana:cache method (file cache) I am trying to find a workaround for this.
enables caching for the file search as says in the Kohana/Core.php file: Whether to use internal caching for [Kohana::find_file], does not apply to [Kohana::cache]. Set by [Kohana::init]
Enable caching true to speed up the file search, and enable the cache module, I am working on a way to cache the queries of DB using the instance used by the module. That would be better than using the file cache. Maybe I am missing something but stuck there right now.

distinguish use cases in NSAutosaveElsewhereOperation

I try to add AutoSave support to the Core Data File Wrapper example
Now if i have a new/untitled document writeSafelyToURL is called with the NSAutosaveElsewhereOperation type.
The bad thing is, I get this type in both typical use cases
- new file: which store a complete new document by creating the file wrapper and the persistent store file
- save diff: where the file wrapper already exists and only an update is required.
Does somebody else already handled this topic or did somebody already migrated this?
The original sample use the originalStoreURL to distinguish those two use cases, which solution worked best for you?
Thanks

CoreData 'Name must begin with lower case letter' - can I get around this?

When I first started my iOS project I could use capital letters in core data to start my property names (FirstName, LastName, ect...). This is extremely beneficial to me since I feed data into CoreData using a web service and plists and the creation of objects inserted into my local CoraData DB is greatly simplified and super fast if all property names match exactly. Which up until now has not been a problem. Currently in xCode 4.3.1 I cannot get around the nameing convention restrictions and it is causing me a huge headache since my remote DB uses capital letters for it's column names which in turn then do not match my local CoreData properties.
Is there anyway to get around this in xCode?
Function to convert the first character to lowercase:
-(NSString *)refactorAttributeName:(NSString*)name {
NSString *first = [[name substringToIndex:1] lowercaseString];
return [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
withString:first];
}
Simple answer is No. If you have any control over the way the data is coming out of your remote DB, you could just do something like:
Select FirstName as firstName, LastName as lastName ...
If that is too much trouble, then you will need to either need to map these in your project or not use Xcode 4.3 and up.
you can always go into the model package and edit the contents file manually. does not mean that this new standard won't bite you later.
I suppose you can try opening the same project in 4.2 use big letter, and then reopening in 4.3, which will honor the old convention
I had similar problem - I wanted to use entity names starting with lower case letter and xcode demanded to use names starting with upper case letter. I resolved this issue in the following way:
Created NSManagedObject subclass for an entity - option available in
Editor menu
Used xcode refactoring to change the name of the created subclass
Refactoring changed also the name of the entity in the Data Model. I believe same method can be used for changning the name of attributes. I used xcode 4.6.1.
I encountered the same problem when mapping my web service JSON response to my Core Data models. Instead of changing the Core Data models I solved it by changing my mapping code to the following:
for (NSString *key in json) {
NSString *keyWithFirstCharLowered = [key stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[key substringToIndex:1] lowercaseString]];
if ([modelClass respondsToSelector:NSSelectorFromString(keyWithFirstCharLowered)]) {
[modelClass setValue:[json valueForKey:key] forKey:keyWithFirstCharLowered];
}
}

Partial caching dependencies in Kentico

How do I use the partial dependency caching in Kentico CMS?
Here's a very common example need I have but can't figure how to set up partial caching with dependencies correctly (in Portal mode, though I think this should apply to the other development modes too):
/Home (with a Repeater)
/News
Item 1 (so path = /News/Item-1)
Item 2 (so path = /News/Item-2)
The Home page has a Repeater web part that lists the most recent news items. It has a Path of "/%" and Document Types filter set to "CMS.News"; obviously also a "Partial cache minutes" value > 0. There is no custom code; just Portal web parts and standard document types.
What is the exact "Partial cache dependencies" string I should use so that when a third news item it is immediately reflected on the Home page, but otherwise uses the cache?
Kentico did release several blog posts including Deep dive: Cache dependencies, but I'm having difficulty applying the theory discussed there to a site. I even asked in comments there some questions, but the answers by the Kentico support there weren't really helpful.
From what I could tell in that post, they said to use node|%CurrentSite.SiteName%}|/News|childnodes which seems to have some magic keywords like node and some macro elements like {%CurrentSite.SiteName%}. (I know that all items need to be lowercase, so already I know their advice isn't real consistent. It should at least be node|%CurrentSite.SiteName%}|/news|childnodes instead. And do I need to force lowercase on the macros?) First of all, that string didn't work for me--it was still caching the Home page Top News repeater (yes, full page caching was turned off); second, how do I build a string like that and debug what it should be? The linked post does have a grid of examples, but it is confusing (to me) and not exhaustive.
Can anyone provide a good example or better blog post reference anywhere that explains this in another way?
EDIT: I realized I asked this question fairly broadly. How about if we narrow it to just answer the question: How do I determine what settings to use to cache a repeater with a dependency to changes in another folder?
The magic words you mentioned in your post are basically the keywords for particular objects. You can see them listed in the caching options description - the "node", "nodes", "nodeid" are listed there as most common for working with nodes. But below then is described the syntax for any object, where you will use that object class name.
Regarding the blog post from the Kentico's CTO and his answers in the comments, it looks like he overlooked or misunderstood your question. you are talking about partial caching and he was giving you examples on the "normal" caching settings. Macros in the touch keys are resolved (lower case or upper case does not matter) in all other caching settings but not in the partial caching. This feature will be available in the upcoming version 6.0.
So, right now you have to hard-code the site name in the touch key cache setting.
I turned on the cache debugging and looked at what cache names were being generated. I saw mine being set to...
node|{%CurrentSite.SiteName%}|/test-section/|childnodes
...which was obviously incorrect and would never work!
It looks like macros do not get resolved within the Partial Cache Dependencies property. So you can't use "{%CurrentSite.SiteName%}" in place of the site name. Here is an example of a partial cache dependency that worked for me...
node|mytestsite|/test-section/|childnodes
Using the above partial cache dependecy, the cache was refreshed as soon as I deleted a sub-item.

Resources