CoreDataQueryでデータを保存する [RubyMotion]

はじめに

前回、"RubyMotion事始め“では、gem, CocoaPodsを用いて外部ライブラリを利用する方法をまとめました。
今回はCoreDataを利用してデータを永続化する方法をまとめます。

Core Data Query 利用準備

RubyMotionでCoreDataを扱うために、cdq (Core Data Query)を利用します。
まずはmotionコマンドでプロジェクトを作成し、

motion create cdq_sample
cd cdq_sample

Gemfileに依存関係を記述します。
画面構成のコードを簡潔にするために、前回同様にProMotionも使用しています。

Gemfile

source 'https://rubygems.org'

gem 'ProMotion'
gem 'cdq'

Gemfileに依存関係を記述したら、bundleコマンドでインストールを行います。

bundle install --path vendor/bundle

次にcdqコマンドでCore Data Queryを使うための準備をしましょう。

bundle exec cdq init

initで作成されるファイルの一つにschemas/0001_initial.rbがあります。
このファイルはrailsでのmigrationファイルのようなもので、スキーマを定義します。


schema "0001 initial" do

  # Examples:
  #
  # entity "Person" do
  #   string :name, optional: false
  #
  #   has_many :posts
  # end
  #
  # entity "Post" do
  #   string :title, optional: false
  #   string :body
  #
  #   datetime :created_at
  #   datetime :updated_at
  #
  #   has_many :replies, inverse: "Post.parent"
  #   belongs_to :parent, inverse: "Post.replies"
  #
  #   belongs_to :person
  # end

end

また、initによりRakefileにも追記が行われています。
これはbuild:simulatorタスク実行時にschema:buildも行われることを表しており、schema:buildタスクを実行することでxcdatamodeldが生成されます。

# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project/template/ios'

begin
  require 'bundler'
  Bundler.require
rescue LoadError
end

Motion::Project::App.setup do |app|
  # Use `rake config' to see complete project settings.
  app.name = 'cdq_sample'
end
task :"build:simulator" => :"schema:build"

Core Data Query でデータを保存してみる

ここから、実際にCore Data Queryを用いてデータを保存してみましょう。
schemas/0001_initial.rbにスキーマを定義します。
今回は単純に、文字列でbodyをもつItemを作ってみましょう。

schema "0001 initial" do

  entity "Item" do
    string :body
  end

end

cdq create modelコマンドでモデルも作成できます。

bundle exec cdq create model item

app/models/item.rb

class Item < CDQManagedObject

end

次に、delegate
CDQincludeし、
on_load
cdq.setupを呼び出すようにします。

app/app_delegate.rb

class AppDelegate < PM::Delegate
  include CDQ
  def on_load(app, options)
    cdq.setup
    open ItemsScreen.new(nav_bar: true)
  end
end

次に、Itemデータを表示する画面を用意します。

app/screens/items_screen.rb

class ItemsScreen < PM::TableScreen
  title "Items"

  refreshable callback: :on_refresh,
    pull_message: "Pull to refresh",
    refreshing: "Refreshing data..."

  def load_item
    @items = [
      {
        cells: Item.all.map do |item|
          {
            title: item.body,
            action: :tapped_item,
            arguments: item,
          }
        end
      }
    ]
    end_refreshing
    update_table_data
  end

  def on_load
    load_item
  end

  def on_refresh
    load_item
  end

  def table_data
    @items ||= []
  end

  def tapped_item(item)
    p "item #{item.body} tapped"
  end
end

準備が出来たので、rakeコマンドを叩きましょう。
シミュレーターが立ち上がります。
このとき、自動的にschema:buildタスクも実行され、xcdatamodeldが生成されます。
まだデータが登録されていないので、テーブルの内容は空です。

rakeコマンドで立ち上がったコンソールから、
直接データを投入してみます。

Item.create body: 'test'

シミュレーターに戻り、画面を下に引っ張って更新してみると、テーブルの内容が増えていることが確認できます。

このとき、シミュレーター上でホームボタンを押し、すぐアプリを立ち上げ直しただけでは登録した情報はそのままです。
しかし、コンソールをexitで抜けた場合や、ホームボタンをダブルタップしてアプリをバックグラウンドからも削除し、その後アプリを起動し直すと登録した情報が消えています。
つまりメモリ上にのみ登録されていたわけです。

データを永続化する手順も簡単です。
もう一度rakeでシミュレータを起動し、再度Item.createでデータを登録してみましょう。
今回は永続化するためにcdq.saveコマンドを実行します。

Item.create body: 'test2'
cdq.save

これでアプリを起動し直してもデータが保存されるようになりました。