MagicalRecord に mogenerator を組み合わせてよいか

CoreDataを使う際に、MagicalRecordに加えてmogeneratorを使う事を推奨しているブログ記事が散見されますが、mogeneratorには以下のようにリジェクトのリスクがあるようです。

筆者はmogeneratorを使っていた事もありましたが、現在は別の理由もあってMagicalRecord単体で使っています。リジェクトのリスクはmogeneratorに限った話しではないですが、注意した方がいいかもしれません。

以上

MagicalRecordでCoreDataをお手軽に使う

iOSアプリでデータを保存(serialize/deserialize)する方法としてCoreDataがありますが、コード量が多く慣れるまでにも時間がかかります。

ここではより簡単なMagicalRecordによって、CoreDataを使ってみます。

MagicalRecordActive Recordパターンを採用したCoreDataのラッパーです。ActiveRecordは、Martin FowlerらのPatterns of Enterprise Application Architectureで名付けられ、Ruby on Railsで普及しました。

MagicalRecordがあれば、Webアプリ開発者でもCoreDataを簡単に扱えるようになり、iOSアプリ開発がより身近に感じられるようになると思います。

前提

CocoaPodsはインストール済みとします。CocoaPodsのインストール方法は以下を参照してください。

iOSアプリのプロジェクト作成

  1. Xcodeを開いて新規プロジェクトを作成します。

     File > New > Project
    
    • Use Core Dataの指定は不要です。
      • 指定すると不要なコードが生成されるため、指定しない事をおすすめします。

MagicalRecordのインストール

  1. Podfile作成

    1. .xcodeprojがあるディレクトリにPodfileファイルを作成します。
    2. Podfileに次の1行を追記します。

      pod 'MagicalRecord'

  2. MagicalRecordインストール

    1. ターミナル上でPodfileと同じディレクトリに移動して以下を実行します。

       pod install
      
  3. 設定

    1. アプリ名/アプリ名-Prefix.pchを開いて次の1行を追記します。

       #import "CoreData+MagicalRecord.h"
      

CoreDataデータモデルの定義と作成

  1. Data Modelを追加

    1. メニューからFile > New > File > Data Modelを選択します。
    2. Model.xcdatamodeldを作成します。
  2. Entityを追加

    1. ツリー上でModel.xcdatamodeldを選択します。
    2. Add EntityをクリックしてEntityを追加します。
    3. Entityを適切な名前に変更します。
    4. Entityの属性(Attributes)や関係(Relationship)を定義します。
  3. Entityから必要なソースコードを自動生成

    1. ツリー上でModel.xcdatamodeldを選択します。
    2. メニューからEditor > Create NSManagedObject Subclass > Next > Next > Createを選択します。

      Use scalar properties for priitive data typesをチェックすると以下のようなスカラー型(定数型)のプロパティがプリミティブなデータ型に変換されます。チェック不要で構いません。

      • Date -> NSTimeInterval.
      • Double -> double.
      • Float -> float.
      • Integer 16/32/64 -> int16_t/int32_t/int64_t
      • Boolean -> BOOL

MagicalRecordの起動/終了処理

  1. 起動処理

    AppDelegete.mファイルを開いてdidFinishLaunchingWithOptionsに起動処理を追加します。

     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
     {
         // 以下を追加
         [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"database_name.sqlite"];
         return YES;
     }
    

    初期化には以下のようなメソッドが用意されています。目的に応じて選択します。

    ローカルのSQLite

     + (void) setupCoreDataStack;
     + (void) setupAutoMigratingCoreDataStack;
     + (void) setupCoreDataStackWithInMemoryStore;
     + (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName;
     + (void) setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(NSString *)storeName;
    

    iCloud

     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)icloudBucket localStoreNamed:(NSString *)localStore;
     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent;
     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent completion:(void(^)(void))completion;
    
  2. 終了処理

    AppDelegete.mファイルを開いてapplicationWillTerminateに終了処理を追加します。

     - (void)applicationWillTerminate:(UIApplication *)application
     {
         // 以下を追加
         [MagicalRecord cleanUp];
     }
    

MagicalRecordでのデータ保存

  • 同期

      Album *album = [Album MR_createEntity];
      album.title = @"Friends";
          :
    
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    

MR_saveメソッドは次期メジャーリリースの3.0からは無くなるので同じ機能を持つMR_saveToPersistentStoreAndWaitを使いましょう。

  • 非同期

      Album *album = [Album MR_createEntity];
      [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
    
          //保存前の処理(保存したいインスタンスの作成など)
          Album *localAlbum = [album MR_inContext:localContext];
          localAlbum.title = @"NeverMind";
              :
    
      } completion:^(BOOL success, NSError *error) {
    
          //保存後の処理(全件取得や件数カウントなど)
    
      }];
    
  • その他

    MagicalRecord / Docs / Saving.md

MagicalRecordでのデータ取得

  • 全件取得

      NSArray *albums = [Album findAll];
    
  • 条件を指定して取得

      NSArray *albums = [Album MR_findByAttribute:@"genre" withValue:@"piano trio" andOrderBy:@"year" ascending:YES];
    
  • その他高度な取得

    MagicalRecord / Docs / Fetching.md

MagicalRecordでのデータ更新

  • データ取得&更新

    あらかじめAlbumのインスタンス(ここではcheckyourhead)を取得しておきます。

      Album *checkyourhead = ...;
      checkyourhead.rate = [NSNumber numberWithInt:5];
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    

MagicalRecordでのデータ削除

  • 全件削除

      [Album MR_truncateAll];
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    
  • 1件削除

    あらかじめAlbumのインスタンス(ここではmellowgold)を取得しておきます。

      Album *mellowgold = ...;
      [mellowgold MR_deleteEntity];
    

MagicalRecordでのデータカウント

  • カウント

      NSNumber *count = [Album MR_numberOfEntities];
    

注意

MagicalRecordでデータの保存、更新、削除を反映する際は必ず以下を実行します。

    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

以上です。MagicalRecordを使うとCoreDataを簡単に扱えます。

OSXでDockerを使う

Dockerに特化した軽量Linuxのboot2dockerを使ってOSXでDockerを使ってみます。Dockerはv0.8でアーキテクチャを変更してOSXに対応し、homebrewにも入ったため誰でも簡単に使えるようになりました。

f:id:slowquery:20140311231722p:plain

インストール

brew cask install virtualbox
brew cask install vagrant
brew install docker
brew install boot2docker

boot2dockerのVMを作成

boot2dockerのVirtualBox用のVMを作成します。

boot2docker init

※ boot2dockerは、Dockerコンテナを動かす目的に特化したTinyCoreLinuxベースの軽量Linuxディストリビューションです。

boot2dockerのVMを起動

boot2docker up  
export DOCKER_HOST=tcp://localhost:XXXX

boot2dockerのVMへ接続(参考)

boot2docker ssh

ユーザ/パスワードは以下です。

user:docker
password:tcuser

f:id:slowquery:20140311231722p:plain

コンテナイメージを探す

以下のサイトにDockerのコンテナがたくさんあります。

例1. Ubuntuのコンテナをダウンロード

Ubuntuのコンテナをダウンロードしてboot2dockerに展開します。

docker pull ubuntu

例1. Ubuntuへログイン

docker run -i -t ubuntu /bin/bash

f:id:slowquery:20140311231933p:plain

例2. CentOSのコンテナをダウンロード

docker pull centos

例2. CentOSへログイン

docker run -i -t centos /bin/bash

トラブル対策

OSXVirtualBox 4.3.8環境で問題が発生するケースがあります。

boot2docker / boot2docker - Kernel panic on VirtualBox 4.3.8 (Mac OS X) #260

現象

解決策

上記現象が発生する場合は以下を実行します。

boot2docker stop
boot2docker delete
boot2docker init

VBoxManage setextradata boot2docker-vm VBoxInternal/CPUM/EnableHVP 1
boot2docker up

yeomanのangular-fullstackでMEAN (MongoDB + Express + AngularJS + Node.js)アプリをお手軽に開発

クライアントサイドのMV※フレームワークの一つにAngularJSがありますが、2012年にバージョン1.0がリリースされ、2013年になって一気に大流行しました。このAngularJSの流行に乗りながら、サーバサイドも含めてJavaScriptで開発するMEAN (MongoDB + Express + AngularJS + Node.js) 構成のスタイルにも注目が集まっています。

ここではyeomanの力を使って以下のような構成のMEAN+αアプリの雛形を簡単に生成してみます。

  • yeoman
    • yo
    • bower
    • grunt
  • AngularJS
  • node.js
  • express
  • passport
  • jade
  • sass
  • Twitter Bootstrap 3
  • MongoDB
  • mongoose
  • Karma
  • CoffeeScript

今回はyeomanのgeneratorとして、全generator中第3位(MEANでは1位)のgithubスター数を獲得しているDaftMonk/generator-angular-fullstackを使用してみます。

前提条件

  • node.js
  • MongoDB
  • compass (gem install compass)

インストール

yeomanのインストール

npm install -g yo

yeomanのangular-fullstackジェネレータのインストール

npm install -g generator-angular-fullstack

アプリ生成

angular-fullstackのアプリ雛形作成

mkdir [app name]
cd [app name]
yo angular-fullstack --jade

--coffeeを付ければJavaScriptの代わりにCoffeeScriptが出力されます。 ※angularとfullstackの間のハイフンが抜けていたので修正しました。

ウィザードでは、全てyesを選択しています。

f:id:slowquery:20140130023534p:plain

アプリ起動

MongoDB起動

mongod

アプリ起動

grunt serve

f:id:slowquery:20140130023708p:plain

ファイルを変更すると自動でリロードされます。

ディレクトリ構成

ディレクトリ構成はわかりやすく、app配下にはクライアントサイド(AngularJS)、lib配下にはサーバサイド(node.s + express)のリソースが格納されています。

.
├── Gruntfile.js
├── app : クライアントサイド (新規リソースはyo angular-fullstack:で生成)
│   ├── bower_components
│   ├── favicon.ico
│   ├── images
│   ├── robots.txt
│   ├── scripts
│   ├── styles
│   └── views
├── bower.json
├── karma-e2e.conf.js
├── karma.conf.js
├── lib : サーバサイド (追加リソースは各自作成)
│   ├── config
│   ├── controllers
│   ├── middleware.js
│   ├── models
│   └── routes.js
├── node_modules
│   ├── bcrypt
│   ├── connect-livereload
│   ├── connect-mongo
│   ├── express
│   ├── grunt
略
│   ├── jade
│   ├── jpegtran-bin
│   ├── jshint-stylish
│   ├── karma
略
│   ├── load-grunt-tasks
│   ├── lodash
│   ├── mongoose
│   ├── mongoose-unique-validator
│   ├── passport
│   ├── passport-local
│   ├── requirejs
│   └── time-grunt
├── package.json
├── server.js : expressのメインファイルです
└── test
    ├── runner.html
    └── spec

その他

今回は雛形作成までとして、今後より詳しい記事を書きたいと思いますが、幾つか必要な作業を書いておきます。

ページ(view)追加

新しいページ(view)を追加するには以下のコマンドを実行します。クライアントサイドのcontroller, route, viewがまとめて自動生成されます。

yo angular-fullstack:route [view名=route名]

注意

  • はじめに--jade--coffeeを付けておくと、以降その設定は引き継がれ毎回指定しなくてもjadeやCoffeeScriptのファイルが生成されます。

  • directive等も同様に生成できます。

ユーザ登録

初期状態だとユーザ登録してもMongoDBにユーザが登録されません。アプリを再起動する度にユーザを削除してテストユーザを作成しているためです。これを解除する為にはserver.jsからdummydata.jsを読み込んでいる部分を変更します。

Hacker Newsの記事をMongoDBに蓄積するPythonアプリケーションをGIthubとHerokuで公開

Hacker NewsのエントリをMongoDBに蓄積するWebアプリをGitHubherokuに公開しました。目的はHacker Newsのエントリの分析で今後そうした機能を公開するかもしれません。MIT Licenseなので好きに使ってください。

f:id:slowquery:20131228184124p:plain

GitHub

sodesign / HackerNewsRecorder

Heroku

Hacker News Recorder