Updated June 26, 2015
Once again, we are talking about using Core Data in RubyMotion. If you’ve missed the earlier posts, you can find them here:
Introduction to Core Data in Motion
Core Data Basics in RubyMotion
Core Data Relationships in RubyMotion
This week, we are delving into loading up that Core Data store with a pre-populated set of data. Once again, Ray Wenderlich’s Core Data tutorial offers us a great starting point. Core Data on iOS 5 Tutorial: How To Preload and Import Existing Data
When I initially started this series, this tutorial had not be re-written. It eventually ended up at the same place I did, however, so let’s just start at the beginning, and see how we eventually get there. Just as a reminder, all the code for this series is based on Ray’s example, and can be found
here
(I have created a RubyMotion project to illustrate this based on his Failed Banks
example. You can find my project here. And all the code relevant to this post can be found in this
branch.
In the basics and relationships posts, we have already created our models, dealt with the persistent store coordinator, managed object context, and the managed object model, and then wired our models together with relationships. So that is our starting point for this exercise.
This is our load function, as translated from Ray’s example, to start.
def self.load
# Finds and opens the json file, from the resources dir, which contains the data to be loaded
path = NSBundle.mainBundle.pathForResource("Banks", ofType:"json")
banks = BW::JSON.parse(NSData.dataWithContentsOfFile(path))
puts(banks)
banks.each do |bank|
FailedBankStore.shared.add_bank do |info, details|
info.name = bank['name']
info.city = bank['city']
info.state = bank['state']
details.close_date = NSDate.dateWithNaturalLanguageString(bank['closeDate'])
details.update_date = NSDate.date
details.zip = bank['zip']
info.details = details
end
end
end
That’s a bit of a wall of text, so let’s break it down. First step, finding the JSON file that contains the data, and reading it in.
# Finds and opens the json file, from the resources dir, which
# contains the data to be loaded
path = NSBundle.mainBundle.pathForResource("Banks", ofType:"json")
banks = BW::JSON.parse(NSData.dataWithContentsOfFile(path))
The JSON file -
Banks.json
, is located in your RubyMotion project’s
resources directory. Then we use the ever-useful
BubbleWrap library’s JSON methods to read in the data. This yields to us an array of bank objects, which are essentially Hashes.
Since we have an array, we’ll now iterate through it, and add_bank for each, populating the bank info and bank detail entities with the related values.
banks.each do |bank|
FailedBankStore.shared.add_bank do |info, details|
info.name = bank['name']
info.city = bank['city']
info.state = bank['state']
details.close_date = NSDate.dateWithNaturalLanguageString(bank['closeDate'])
details.update_date = NSDate.date
details.zip = bank['zip']
info.details = details
end
end
For clarity’s sake, it’s probably worth a look at the add_bank method, which simply creates and yields the new bank info and bank details entities for us, and saves the populated objects into the managed context.
def add_bank
# Yield a blank, newly created bank entity, then save the model.
yield NSEntityDescription.insertNewObjectForEntityForName('FailedBankInfo', inManagedObjectContext:@context),
NSEntityDescription.insertNewObjectForEntityForName('FailedBankDetails', inManagedObjectContext:@context)
save
end
Now that we have all that, all we have to do is run our project in the simulator (
rake), and invoke
FailedBankStore.load
from the REPL, and bingo, we have a pre-populated SQLite database. The next time you run your app, you’ll see the all the data you just loaded.
That seems pretty simple, doesn’t it? And it is. Pretty simple. Or maybe I should say, pretty simplistic. This actually works quite well, with a relatively small data set. This example, with a working set of data, can be downloaded and run from this branch of the repository.
However, once you start dealing with larger datasets (mine had 244,292 items), you will find this simple case breaks down rapidly. How we deal with really large datasets is, of course, our next topic. :-)
Until then…
If you found this post enlightening, you will find the ebook I wrote on these topics (and more) will allow you to spend more time working on your iOS application features, instead of fighting with Core Data for hours (or days).