2012年12月5日水曜日

rubymotionとrailsの連携を試行錯誤した話

この記事はRubyMotion Advent Calendar 2012の5日目記事です。

rubymotionメリットのひとつに、サーバサイド(Rails)とクライアントサイドが同じ言語でかけることがあると思いますが、
思いの外Railsとどう連携していくかの情報が少ないような気がします。
なので他の人の参考になればと、個人的に試行錯誤したことを残しておこうと思います。

ちなみに、one minutesというアプリを、rubymotionで作りましたので、よければダウンロードしてください。

試行錯誤1、babble-wrapで都度処理を書く

先述のone minutesでは、表示させるニュース情報をサーバからjsonで取得するだけの単純作業なので、以下の様な感じで実装しました。

  1. BW::HTTP.get(SERVER_URL) do |response|  
  2.   if response.ok?  
  3.     @data = BW::JSON.parse(response.body.to_str)  
  4.   else  
  5.     App.alert(response.error_message)  
  6.   end  
  7. end  

実装はかなり楽でしたが、複数情報を取得したい先がある場合や、postを行うときには、かなり面倒なことになってしまいました。
それが↓です。

試行錯誤2、babble-wrapで都度処理を書く(その2)

ソーシャルアプリを作ろうとした際の実装です。
アプリ概要は、facebookみたいなものなので、記事の投稿、投稿に対するコメント、投稿に対するいいね、それぞれを表示させるタイムラインの実装が必要でした。
それが下記コード群です。

#記事読み込み
  1. BubbleWrap::HTTP.get("#{SERVER_URL}/entries.json?page=#{@page}"do |response|  
  2.   if response.ok?  
  3.     json = BubbleWrap::JSON.parse(response.body.to_str)  
  4.     unless json.count == 0  
  5.       @table_dates << json  
  6.       self.tableView.reloadData  
  7.       @page += 1  
  8.       @readMoreButton.enabled = true  
  9.       @readMoreButton.hidden = false if @page  
  10.     else  
  11.       @page = nil  
  12.       @readMoreButton.hidden = true  
  13.     end  
  14.   else  
  15.     App.alert(response.error_message)  
  16.    end  
  17. end  
#記事投稿
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/entries.json", {payload: data})  
#コメント
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/comments.json", {payload: data}) do |response|  
  2.    if response.ok?  
  3.      App.alert("コメントしました")  
  4.    elsif response.status_code.to_s =~ /40\d/  
  5.     App.alert("comment failed")  
  6.    else  
  7.     App.alert(response.error_message)  
  8.   end  
  9. end  
#いいね
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/likes.json", {payload: data}) do |response|  
  2.    if response.ok?  
  3.       App.alert("likeしました")  
  4.     else  
  5.      App.alert(response.error_message)  
  6.    end  
  7.  end  

企画自体が没になったため、コレ以上コードは書いていないのですが、
重複が多く、メンテナンス性も非常に悪いものができてしまいました。

で、このあとECアプリを作ることになりました。
これまでの経験を踏まえ、もう少しRailsライクに実装したいと感じるように。

具体的には、
1.new、find、save、allなどで情報が取得や保存ができるように
2.バリデーションエラーは、その内容までも分かるように
3.ネットワークエラーなどがでたら、バリデーションエラーなどとは別に判別できるように

という理想を掲げ、作ってみた現実(ライブラリ)はこちら。
https://github.com/face-do/motion-rails-model

初めて作ったライブラリでもあり、非常にできはよくないのですが、それでも一応の理想は実現できました。
(といっても、babble-wrapのさらにwrapperライブラリだったりしますが。。。)

使い方としては、最初にアクセスしたいURLやbasic認証の情報を入力


  1. RM::Model.set_url("#{URL}/api/")  
  2. RM::Model.set_username("username")  
  3. RM::Model.set_password("password")  

その後モデル用のクラスを作り、ライブラリを継承。

  1. class Orders < RM::Model  
  2.   attr_accessor :name  
  3.    
  4.   def attributes_update(json)  
  5.     @name = json['name']  
  6.     super  
  7.   end  
  8. end  

これで、

  1. order = Orders.new  
  2. order.name = "hogehoge"  
  3. order.save do |x|  
  4.   if x.ok?  
  5.     App.alert("保存しました。")  
  6.   end  
  7. end  

とかすると、
railsに対して
/api/orders.json?name=hogehoge
のpostメソッドを実行するし、

  1. Orders.find(1) do |x|  
  2.   if x.ok?  
  3.     @order = x.body  
  4.   end  
  5. end  

で、
/api/orders/1.json
のgetをしたりします。

またgetしてきた、Objectに対してsaveをすると、
/api/orders/1.json
に対してputをするようになってます。

これを作った後、メタプログラミングrubyを読みまして、
もう少し抽象化ができそうな気がしているので、機会を見て修正していく予定です。

0 件のコメント:

コメントを投稿