RubyMotion is great for quickly prototyping apps but it lacks the data modelling tools that Xcode provides. Luckily, using Core Data with RubyMotion can actually be easier and quicker with a little help from some 3rd party libraries.
How to Troubleshoot Apps for the Modern Connected Worker
Ā
Simpler Core Data with RubyMotion
1. Simpler Core Data
with RubyMotion
StefĆ”n Haļ¬iĆ°ason
http://stefan.haļ¬idason.com
@styrmis
2. Why RubyMotion?
ā¢ Promises increased developer productivity
ā¢ Brings the ļ¬exibility of Ruby to iOS and OSX development
ā¢ Bridges directly to Obj-C libraries: no intermediate glue
code
ā¢ A REPL for working with your app live!
ā¢ Make tweaks quickly
ā¢ Build whole views programmatically on the ļ¬y
3. Why Core Data?
ā¢ Optimised for low-memory/embedded (iOS)
devices
ā¢ Mature data access/persistence framework
ā¢ Also available on OSX
ā¢ Works with iCloudāfree cloud syncing for your
app
4. Core Data is Difļ¬cult
ā¢ Provided boilerplate code unnecessarily complex
ā¢ An object graph thatās persisted to an SQLite
database
ā¢ Suggests relational access, which is not quite
the case
ā¢ Typical patterns for working with relational data
are not optimal here
5. RubyMotion is āEasyā
ā¢ Friendliness of Ruby
ā¢ An ARC equivalent is included
ā¢ Lots of work done to abstract complexity away
ā¢ More concepts similar to other OO languages
6. Core Data and RubyMotion
ā¢ No equivalent of Xcodeās visual data modeller
ā¢ How do I deļ¬ne my data model?!
ā¢ What about versioning?!
ā¢ How will I handle migrations?
7. What we need
ā¢ Our data model (NSEntityDescriptions +
NSRelationshipDescriptions forming our
NSManagedObject)
ā¢ A Core Data Stack (NSManagedObjectModel +
NSPersistentStoreCoordinator +
NSManagedObjectContext)
ā¢ A workļ¬ow for versioning and migrating
between versions
8. Deļ¬ning Our Data Model
ā¢ We would normally do this in Xcode
ā¢ Visual Editor for .xcdatamodel bundles
ā¢ Integrated handling of versioning and custom
migration code
ā¢ Automatic lightweight (schema) migrations
ā¢ How do we achieve this with RubyMotion?
9. Options for RubyMotion
ā¢ Handle everything programmatically (low
level)
ā¢ Use Xcode to work with .xcdatamodel ļ¬les,
copy in each time
ā¢ Use a Ruby library for creating .xcdatamodel
ļ¬les
10. Handling Everything
Programmatically
entity = NSEntityDescription.alloc.init
entity.name = 'Task'
entity.managedObjectClassName = 'Task'
entity.properties =
[ 'task_description', NSStringAttributeType,
'completed', NSBooleanAttributeType ].each_slice(2).map do |name, type|
property = NSAttributeDescription.alloc.init
property.name = name
property.attributeType = type
property.optional = false
property
end
11. Handling Everything
Programmatically
entity = NSEntityDescription.alloc.init
entity.name = 'Task'
entity.managedObjectClassName = 'Task'
entity.properties =
[ 'task_description', NSStringAttributeType,
'completed', NSBooleanAttributeType ].each_slice(2).map do |name, type|
property = NSAttributeDescription.alloc.init
property.name = name
property.attributeType = type
property.optional = false
property
end
Not all that bad, but we want to use .xcdatamodel ļ¬les
14. Workļ¬ow
ā¢ Create schema ļ¬le in schemas directory, e.g.
schemas/001_initial.rb
ā¢ Build the schema
ā¢ Add a new schema version, e.g.
002_add_new_fields.rb
ā¢ Rebuild the schema
ā¢ Thatās it!
15. Workļ¬ow
$ echo "gem 'ruby-xcdm', '0.0.5'" >> Gemfile
$ bundle install
$ rake schema:build
Generating Data Model learn-xcdm
Loading schemas/001_initial.rb
Writing resources/learn-xcdm.xcdatamodeld/1.xcdatamodel/
contents
$ rake # The default rake task is to run the app in the simulator
(main)> mom = NSManagedObjectModel.mergedModelFromBundles(nil)
=> #<NSManagedObjectModel:0x8fa7690>
(main)> mom.entities.count
=> 2
(main)> mom.entities.first.name
=> "Article"
(main)> mom.entities.first.propertiesByName
=> {"body"=>#<NSAttributeDescription:0x8e5db30>,
"title"=>#<NSAttributeDescription:0x8ea4770>}
16. Advantages of using ruby-
xcdm
ā¢ No magic: generates XML from a schema
ā¢ Schema versions are fully text-based and
readable, making them well-suited to version
control
ā¢ Can compile our versions into .xcdatamodeld
bundles, completely removing dependence on
Xcode
18. Core Data Query
ā¢ From the developers of ruby-xcdm
ā¢ Abstracts away much of the complexity of Core
Data
ā¢ All you need is your .xcdatamodeld bundle
19. Core Data Query in Action
# app/models/task.rb
class Task < CDQManagedObject
end
!
# app/app_delegate.rb
class AppDelegate
include CDQ
!
def application(application,
didFinishLaunchingWithOptions:launchOptions)
cdq.setup
true
end
end
21. Core Data in Action
Author.where(:name).eq("Emily")
Author.where(:name).not_equal("Emily")
Author.limit(1)
Author.offset(10)
Author.where(:name).contains("A").offset(10).first
!
# Conjuctions
Author.where(:name).contains("Emily").and.contains("Dickinson")
Author.where(:name).starts_with("E").or(:pub_count).eq(1)
!
# Nested Conjuctions
Author.where(:name).contains("Emily").and(cdq(:pub_count).gt(100).or.lt(10)
)
!
# Relationships
Author.first.publications.offset(2).limit(1)
cdq(emily_dickinson).publications.where(:type).eq('poetry')
!
class Author < CDQManagedObject
scope :prolific, where(:pub_count).gt(50)
end
22. Takeaways
ā¢ Donāt be put off by the Xcode boilerplate: Core
Data doesnāt have to be that hard
ā¢ With CDQ, Core Data is arguably easier to use
with RubyMotion rather than harder
ā¢ XCDM, CDQ and RubyMotion Query (all by
Inļ¬nitered) are all worth taking a look at
23. Next Steps
ā¢ In the coming weeks Iāll be researching and writing
about:
ā¢ How to best handle heavyweight/data migrations
in RubyMotion
ā¢ Deconstructing the āmagicā in Core Data Query
ā¢ RubyMotion development best practices
StefĆ”n Haļ¬iĆ°ason
http://stefan.haļ¬idason.com
@styrmis