Rails5のAPImodeでアプリケーションを作成するところまでやってみた話
やったこと
開発しているiosアプリのAPIを作りたく、せっかくなら18日に出たRails5のベータでも使ってみようと思い、環境を構築した。
rbenvのアップデート
rbenvを使っているのだが、rails5はruby2.2.2以上が必要だったのでアップデートをする必要があった。
# ruby-buildをアップデート $ brew upgrade ruby-build $ rbenv install 2.2.3 # 今回作成するアプリケーションにのみ2.2.3を使用する $ rbenv local 2.2.3 # 設定結果を確認 $ rbenv versions
rails5のインストール
本当はrailsアプリケーション内のGemfileで管理したかったのだが、
$ rails new my_api --api
を試してみたかったので普通に
$ gem install rails --pre
を叩いた
APImodeでのアプリケーション作成
http://edgeguides.rubyonrails.org/api_app.html を参考に
$ rails new my_api --api
と打ってみる。
generateされたアプリケーションのapplication.rb
を見てみると
config.api_only = true
application_controller.rb
も
class ApplicationController < ActionController::API end
とAPIモードでのrailsアプリケーションが生成されていた。
起動させてみる
なにも考えずに
$ bundle exec rails server => Booting Puma => Rails 5.0.0.beta1 application starting in development on http://localhost:3000 => Run `rails server -h` for more startup options => Ctrl-C to shutdown server I, [2015-12-26T13:58:52.252332 #10939] INFO -- : Celluloid 0.17.2 is running in BACKPORTED mode. [ http://git.io/vJf3J ] Puma 2.15.3 starting... * Min threads: 0, max threads: 16 * Environment: development * Listening on tcp://localhost:3000
WeblickではなくPumaが立ち上がった。(rails5がpumaを採用しているのか、apiモードのみなのかはまだ調べられていない。というか4.1系をずっと使っていたのでどこかのタイミングで変わったのか、、?)
とりあえずアクセスするといつものページが表示されたので、ひとまず起動はうまくいったっぽい。
APIっぽい仕事をさせてみる
class PostsController < ApplicationController def index @posts = Post.all render json: @posts end def show @post = Post.find_by(params[:id]) render json: @post end end
上記のような適当なコントローラを作成して(省略しますがモデルやルーティングも)
localhost:3000/posts/1
を叩いたら
{"id":1,"name":"hogehoge","contents":"fugafuga","created_at":"2015-12-26T05:46:08.955Z","updated_at":"2015-12-26T05:46:08.955Z"}
と結果が返ってきてくれた。
なにが嬉しいのか
正直上のようにjsonで返すことを明記すれば今までのrailsでも同じような挙動になっていたはず。(というかそのようにAPIサーバをrailsで構築していたものを多いと思う。もちろんGrapeとか使っているのも多いけど)
おそらく僕がリファレンスなどを全然読めてないので、もっとAPIに特化したうまい書き方があるはず。
また、今回のAPIモードの最大のポイントはAPIサーバとして必要最低限のミドルウェアで動かせる、というところのような気がしているのでもっと大きなデータで検証とかしてみたいと思った。
そんなわけでさらっと使ってみただけだと、なにが嬉しいのかあまり実感できなかったが、ミドルウェア周りの話とかAPサーバの話とか、単に自分に知識がないから実感できていないだけの気がしたので勉強します。。。
Realmを用いて合コンで活躍するアプリを開発した
今日の話
Realm使いやすい!おすすめ!ってはなしと合コンでは是非我々のアプリ使ってって話
Realmとは
CoreDataやSQLiteに変わる次世代Mobileデータベースです。
Realm is a mobile database: a replacement for SQLite & Core Data
メリット
- Androidに対応していること→i/A際を意識せずDB設計できること
- SQLiteより速いらしい
- PrimaryKeyがある。
- NSManagedObjectContextなしでオブジェクトが生成できる。
- RLMResultsが良い
- NSPredicate、NSCompoundPredicateを利用してクエリを作れる
- RealmBrowserでDBをGUIで確認できる
デメリット
- オートインクリメントがない
- FetchRequestが弱い→limitとかない
導入方法
Podfile内に下記を追記 pod install
pod 'RealmSwift' #Objective-Cなら pod 'Realm'
使い方
モデル定義
class Person: Object { // オプショナル使える dynamic var name: String? = nil dynamic var id = 0 //数値をオプショナルで扱う場合はRealmOptionalでラップする let age = RealmOptional<Int>() //プライマリーキーの設定も可能 override static func primaryKey() -> String? { return "id" } }
CREATE
//Realmオブジェクト作って、write使って書き込む let realm = try! Realm() try! realm.write() { //オブジェクト生成 var person = realm.create(Person.self, value: ["Jane", 27]) //プロパティの設定 person.age.value = 28 }
READ
let realm = try! Realm() // 文字列で検索条件を指定します var tanDogs = realm.objects(Dog).filter("color = 'tan' AND name BEGINSWITH 'B'") //Result型で返ってくるので、ここからまたフィルタリングできる let predicate = NSPredicate(format: "name CONTAINS %@", "C") let tanDogs2 = tanDogs.objects(Dog).filter(predicate)
UPDATE
// 1.トランザクションを開始して、オブジェクトを更新する try! realm.write { author.name = "Thomas Pynchon" } // 2.プライマリーキー設定している時 // 以前に保存したものと同じプライマリキーを持つBookオブジェクトを作成する let cheeseBook = Book() cheeseBook.title = "Cheese recipes" cheeseBook.price = 9000 cheeseBook.id = 1 // id = 1のBookオブジェクトの値を更新する // ここでid = 1のBookオブジェクトがRealmに保存されていない場合は、新しいBookオブジェクトが追加されます。 try! realm.write { realm.add(cheeseBook, update: true) }
→プライマリーキーを設定したが、なぜかエラーが出てアップデートできなかった。 そのため、1案を採用
DELETE
// トランザクションを開始してオブジェクトを削除します try! realm.write { realm.delete(cheeseBook) } // Realmに保存されているすべてのオブジェクトを削除します。 try! realm.write { realm.deleteAll() }
Realmまとめ
- NSManagedObjectContextとか使わないで、CRUDできるのでCoreDataなどに比べて初期導入コストが低い
- i/A差異が生まれないので、DB定義書を一つで管理できる→保守運用を考えるとかなりありがたい
フィーリングマッチについて
合コンをした際、「あの子は誰が好きなんだろー?知りたいなー」とか必ず思うと思います。 フィーリングマッチはその欲望を叶えます。
使い方
- 合コンの参加者を登録します。
2.意中の相手を選びます。
3.結果を見ます
マッチング相手は完全に非公開
誰と誰がマッチングしたかは非公開です。
何組マッチングしたかだけ知ることができます。
そこからはお酒を飲みながら、探りあいましょう
いかがでしょうか?
操作も簡単、プライバシーも守ります。
飲み会が盛り上がること間違いなし!!!
CarrirWaveでgoogle cloud strageにファイルアップロードする
railsで画像ファイルをアップロードするときに CarrirWave
を使うことはよくあると思うのだけれど、今回そのアップロード先に使ってみたかったgoogle clowd strage
を選択した。
AWSのs3についての記事はたくさんあるものの、google clowd strage
についての日本語の記事があまりなく、英語が拙い自分にとってはつらかったのでメモ
基本的に参考した記事はこれ http://www.codediode.io/lessons/8223-upload-files-to-google-cloud-storage-with-carrierwave
上の通りにやっていけば基本的に問題ないはずなのだが、なにせ英語、、、
まずはgemを入れる
gem 'carrierwave' gem 'mini_magick' gem 'fog'
carriewave
はご存知画像アップロードのためのgem、 mini_magick
は画像のリサイズなどを行なってくれる。fog
というgemはクラウドサービス向けのgemでcarriewave
と組み合わせるとアップロードの向き先を AWS
やGoogle Compute Engine
などに出来たりする。
carriewave
のリポジトリには fog-google
というgemを使うよう書いてあるのだが、fog
でも普通に動いた。
https://github.com/carrierwaveuploader/carrierwave#user-content-using-google-storage-for-developers
googleのAPIキーを設定する
development: google_storage_access_key_id: "HOGEHOGE-ID" google_storage_secret_access_key: "HOGEHOGE-SECRET"
ここのkeyとidがいったいどこのなんの値を入れればよいのか、全然わからなかった。
いろいろいじって見たところ、
の「設定」から
「相互運用性」のタブをクリックし、その中で相互運用アクセスを許可するとアクセスキーと非公開というものが発行される。(キャプチャは相互運用アクセスの設定済みのもの)
このアクセスキーがidで非公開がsecretとなる。(まあsecretは非公開なのだが、わかりにくい、、、)
ただ僕の場合はsecret.yml
にキーをベタで書くのが嫌だったので
Railsで環境変数をライトに使う - MIKAZUKI 開発者ブログ
のように環境変数を使うようにした。
development: google_storage_access_key_id: ENV["GOOGLE_STORAGE_ACCESS_KEY_ID"] google_storage_secret_access_key: ENV["GOOGLE_STORAGE_SECRET_ACCESS_KEY"]
#gemが必要 GOOGLE_STORAGE_ACCESS_KEY_ID = "hogehoge_id" #相互運用性のアクセスキー GOOGLE_STORAGE_SECRET_ACCESS_KEY = "hogehoge_secret" #相互運用性の非公開
あとは http://www.codediode.io/lessons/8223-upload-files-to-google-cloud-storage-with-carrierwave の通り進めていけばオーケー
model と uploader を作成する
$ rails g model Image name:string file:string
$ rails g uploader Image
class Image < ActiveRecord::Base mount_uploader :file, ImageUploader end
strageをfogに設定
class ImageUploader < CarrierWave::Uploader::Base storage :fog end
設定ファイルの記述
CarrierWave.configure do |config| config.fog_credentials = { :provider => 'Google', :google_storage_access_key_id => Rails.application.secrets.google_storage_access_key_id, :google_storage_secret_access_key => Rails.application.secrets.google_storage_secret_access_key } config.fog_directory = 'hogehoge-bucket' #GCEのbucketの名前 end
これで設定は完了。
僕の場合はAPIで使いたかったのでviewは用意していなかったが、上で紹介した参考サイトにviewのサンプルもあるので画面から登録する場合はそちらを参考にして欲しい。
ちかれた
CentOs golang環境構築
必要そうなものをインストール
$ sudo yum install curl git make bison gcc glibc-devel
golang
のバージョン管理ツールであGVM
をインストールする
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
今回はgolang
の1.4.2
をインストール
$ gvm install go1.4.2
失敗する
##### Building Go bootstrap tool.
cmd/dist
ERROR: Cannot find /home/mikazuki_ttp/go1.4/bin/go.
Set $GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4.
./make.bash: line 121: /home/mikazuki_ttp/go1.4/bin/go: No such file or directory
さあどうしたものか
いろいろ調べた結果 https://github.com/moovweb/gvm/issues/124 gitのバージョンを上げて解決している例がちらほら
そういえば yum update
しないで 思考停止して sudo yum install git
してるな、、ということで
$ sudo yum update
そして
$ yum list | grep git
fprintd.x86_64 0.1-22.git04fd09cfa.el6 @base
fprintd-pam.x86_64 0.1-22.git04fd09cfa.el6 @base
git.x86_64 1.7.1-3.el6_4.1 @base
...
あれ、、、yumでは2.x系のgitをインストール出来ないのか、、、
なので http://qiita.com/sirone/items/2e233ab9697a030f1335 の記事を参考にgitを直接入れる
$ sudo yum remove git
$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
$ wget https://www.kernel.org/pub/software/scm/git/git-2.2.0.tar.gz
$ tar -zxf git-2.2.0.tar.gz
$ cd git-2.2.0
$ make prefix=/usr/local all
$ make prefix=/usr/local install
でうまくいくはずが
install -d -m 755 '/usr/local/bin'
install -d -m 755 '/usr/local/libexec/git-core'
install: cannot change permissions of `/usr/local/libexec/git-core': No such file or directory
make: *** [install] Error 1
パーミッションを変えて再チャレンジ
& git --version
=> git version 2.2.2
でけた
リベンジ!
gvm install go1.4.2
gvm use go1.4.2
go version
=> go version go1.4.2 linux/amd64
golangが無事入りました〜!
apache起動時にPermission deniedで怒られる
いきなりapacheが動かなくなり、原因が意外なところにあったのでメモ
いきなり運用していたサーバが応答しなくなったので、とりあえず再起動でもするか、とsudo service httpd restart
を実行。
すると
httpd: Syntax error on line 1 of /etc/httpd/conf/httpd.conf: Cannot load /home/mikazuki_ttp_gmail_com/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/passenger-5.0.13/buildout/apache2/mod_passenger.so into server: /home/mikazuki_ttp_gmail_com/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/passenger-5.0.13/buildout/apache2/mod_passenger.so: cannot open
shared object file: Permission denied
というエラーとともに失敗してしまった。
Permission なんていじってないしなぁと思いつつ権限を確認してみると、問題なく設定されていた。
(念のため sudo chmod 777 /etc/httpd/conf/httpd.conf: Cannot load /home/mikazuki_ttp_gmail_com/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/passenger-5.0.13/buildout/apache2/mod_passenger.so
とかしてみるけど案の定効果なし)
なんかこんな事最初にインフラを構築した時に遭遇した気がしたので自分の昔書いたメモを見てると、どうやらSElinuxによる影響が怪しそう
sudo setenforce 0
でSElinuxを無効化してやると無事動くようになった!
GCP(Google Clowd Platform)の無料期間が終わったので、有料版にアップデートしたのだが、その際に設定もリセットされてしまったのだろうか。。。
javaのDate型でrubyのDateTimeを受け取る
ネイティブはjava(android)、バックエンドはruby(rails)で書かれているアプリケーションのandroid側のコードを触った時の出来事。普段はサーバサイドしか書いていないのでしょーもないことでハマってしまったのでメモ
railsがAPIが提供してネイティブ側でそれをごにょごにょしているのだが、railsのモデルが作るcreated_atのフォーマットがjavaのDateだとうまく受け取れなかった。
created_atのフォーマットはこんな感じ
{ "created_at": "2013-07-16T22:52:36Z" }
この辺を見てみると http://jp.androids.help/q2228
Gsonを生成するときに上記のフォーマットを指定してあげればいいらしい
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss") // こいつを追加した
.create();
これで動くようになりました!
ネイティブも書けるようになりたいです、、、
エミュレータのみでandroid wearの開発環境をつくる
wearを使ったandroidアプリのコードを触る機会があったのだが、自分が実機を持っていなかったので、確認できる環境をエミュレータonlyで構築した。
基本的にはこのへんのリンクのとおりにやればうまくいくはずなんだけど1点はまったところがあったので備忘録的に記録しておく
参考にしたブログ http://lastshooting.blogspot.jp/2014/08/android-wear.html
android wearがエミュレータのandroidに入らない
エミュレータのandoridにgoogle playを入れてそこからwearのアプリをインストールしたものの、お使いの端末はこのバージョンに対応していません
と表示されてしまいandroid4.4.4ではインストールできなかった。
5.0.0ならいけるだろ、と思いエミュレータのバージョンを上げてみたが、相変わらずお使いの端末はこのバージョンに対応していません
の表示のままだったので、バージョンの問題ではないような気がして、apkファイルを直接入れた。
ちょうど同じような現象に遭遇されている方がいたので http://qiita.com/mapyo/items/f617be64d3e3f2cee352
の通りにやったのだがgoogle側が対応しているのか、
http://apps.evozi.com/apk-downloader/
にandroid wearのURLやIDを入れてもwe have run out of device to fetch your apk
と出てしまいダウンロード出来なかった。
なので
http://www.apkmirror.com/
からandroid wear
を検索してバージョンを選んで(一番新しいやつを選んだら4.4.4には入らなかった)ダウンロード。
そのzipをGenymotion上にドラッグ&ドロップでインストール。