Skip to content
This repository was archived by the owner on Feb 21, 2026. It is now read-only.

Repository files navigation

MotionRecord

Miniature ActiveRecord for RubyMotion

Everything you need to start using SQLite as the datastore for your RubyMotion app.

🐢 Android support should be coming soon

Gem VersionCode ClimateTest Coverage

Installation

Add this line to your Gemfile:

gem"motion_record"

On iOS, MotionRecord uses motion-sqlite3 as a wrapper for connecting to SQLite, so add these too:

gem"motion-sqlite3"# Requires the most recent unpublished version of motion.h# https://github.com/kastiglione/motion.h/issues/11gem"motion.h",:git=>"https://github.com/kastiglione/motion.h"

And then execute:

$ bundle

MotionRecord::Base

MotionRecord::Base provides a superclass for defining objects which are stored in the database.

classMessage < MotionRecord::Base# That's all!end

Attribute methods are inferred from the associated SQLite table definition.

message=Message.new(subject: "Welcome!")# => #<Message: @id=nil @subject="Welcome!" @body=nil, @created_at=nil ...>

Manage persistence with create, save, destroy, and persisted?

message=Message.create(subject: "Welcome!")message.body="If you have any questions, just ask us :)"message.save# SQL: UPDATE messages SET subject = ?, body = ?, ... WHERE id = ?# Params: ["Welcome!", "If you have any questions, just ask :)", ..., 1]message.destroymessage.persisted?# => false

Timestamp Columns

If any of the columns are named created_at or updated_at then they are automatically serialized as Time objects and set to Time.now when the record is created or updated.

MotionRecord::Schema

Define and run all pending SQLite migrations with the up! DSL.

defapplication(application,didFinishLaunchingWithOptions:launchOptions)MotionRecord::Schema.up!domigration1,"Create messages table"docreate_table:messagesdo |t|
t.text:subject,null: falset.text:bodyt.integer:read_att.integer:remote_idt.float:satisfaction,default: 0.0t.timestampsendendmigration2,"Index messages table"doadd_index:messages,:remote_id,:unique=>trueadd_index:messages,[:subject,:read_at]endend# ...end

Schema Configuration

By default, MotionRecord will print all SQL statements and use a file named "app.sqlite3" in the application's Application Support folder. To disable logging (for release) or change the filename, pass configuration options to up!

resource_file=File.join(NSBundle.mainBundle.resourcePath,"data.sqlite3")MotionRecord::Schema.up!(file: resource_file,debug: false)# ...

You can also specify that MotionRecord should use an in-memory SQLite database which will be cleared every time the app process is killed.

MotionRecord::Schema.up!(file: :memory)# ...

MotionRecord::Scope

Build scopes on MotionRecord::Base classes with where, order and limit.

Message.where(body: nil).order("read_at DESC").limit(3).find_all

Run queries on scopes with exists?, first, find, find_all, pluck, update_all, and delete_all.

Message.where(remote_id: 2).exists?# => falseMessage.find(21)# => #<Message @id=21 @subject="What's updog?" ...>Message.where(read_at: nil).pluck(:subject)# => ["What's updog?", "What's updog?", "What's updog?"]Message.where(read_at: nil).find_all# => [#<Message @id=20 ...>, #<Message @id=21 ...>, #<Message @id=22 ...>]Message.where(read_at: nil).update_all(read_at: Time.now.to_i)

Run calculations on scopes with count, sum, maximum, minimum, and average.

Message.where(subject: "Welcome!").count# => 1Message.where(subject: "How do you like the app?").maximum(:satisfaction)# => 10.0

MotionRecord::Serialization

SQLite has a very limited set of datatypes (TEXT, INTEGER, and REAL), but you can easily store other objects as attributes in the database with serializers.

Built-in Serializers

MotionRecord provides a built-in serializer for Time objects to any column datatype.

classMessage < MotionRecord::Baseserialize:read_at,:timeendMessage.create(subject: "Hello!",read_at: Time.now)# SQL: INSERT INTO messages (subject, body, read_at, ...) VALUES (?, ?, ?...)# Params: ["Hello!", nil, 1420099200, ...]Message.first.read_at# => 2015-01-01 00:00:00 -0800

Boolean attributes can be serialized to INTEGER columns where 0 and NULL are false and any other value is true.

classMessage < MotionRecord::Baseserialize:satisfaction_submitted,:booleanend

Objects can also be stored to TEXT columns as JSON.

classSurvey < MotionRecord::Baseserialize:response,:jsonendsurvey=Survey.create(response: {nps: 10,what_can_we_improve: "Nothing :)"})# SQL: INSERT INTO surveys (response) VALUES (?)# Params: ['{"nps":10, "what_can_we_improve":"Nothing :)"}']survey# => #<Survey: @id=1 @response={"nps"=>10, "what_can_we_improve"=>"Nothing :)"}>

RubyMotion doesn't have a Date class, but as long as you're okay with using Time objects with only the date attributes, you can serialize them to TEXT columns:

classUser < MotionRecord::Baseserialize:birthday,:dateenddrake=User.create(birthday: Time.new(1986,10,24))# SQL: INSERT INTO users (birthday) VALUES (?)# Params: ["1986-10-24"]# => #<User: @id=1, @birthday=1986-10-24 00:00:00 UTC>

Custom Serializers

To write a custom serializer, extend MotionRecord::Serialization::BaseSerializer and provide your class to serialize instead of a symbol.

classMoneySerializer < MotionRecord::Serialization::BaseSerializerdefserialize(value)raise"Wrong column type!"unless@column.type == :integervalue.centsenddefdeserialize(value)raise"Wrong column type!"unless@column.type == :integerMoney.new(value)endendclassPurchase < MotionRecord::Baseserialize:amount_paid_cents,MoneySerializerend

MotionRecord::Association

TODO

Contributing

Please do!

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

About

ActiveRecord for RubyMotion

Resources

Stars

28 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages