打倒COOKPAD!!Rails4とNokogiriでレシピまとめサイトを作ってみた
こんにちは。ichikoichです。
初めてWebサービスを作り、嬉しくなったのでブログを書いてみました。
作ったもの
COOKPAD, 楽天レシピのレシピをつくレポ数順に並べたまとめサイトを作りました。
「レシピの新聞」というコンセプトで、「Recipe + Paper = ReciPaper」です。
個人的に見てておしゃれだなと思ったPinterestのレイアウトを採用しました。
なぜレシピまとめなのか
奥さんが、毎日3〜4時間レシピサイトを手動で横断検索していたからです。
特にCOOKPADの人気ランキングが有料会員のみ見れるということもあって、無料でさらに見やすくみせてやりたい!と思いました。
振り返って思うこと
実際に開発にかけた時間は1週間くらいなのですが、ほんとに色々なことを学べました。
自分が今回作ったものは「OSSの寄せ集め」です。OSSすげーです。
UI
レスポンシブに対応するために、Twitter Bootstrapを使いました。自分は本開発で初めてレスポンシブという言葉を知りました。実際にアクセス解析すると、ほとんどがスマホからのアクセスで、レスポンシブは必須だなと思いました。
「Pinterestのレイアウトにしたい」という想いがあり、Wookmark jQuery PluginというCSSを使わせていただきました。
最初は、CSS-Only Pinterest Style Columns Layout | CSSDeckというJavaScript無しでスタイルシートで実現するテクニックを採用したのですが、並び方が左➡右にしかならず制御できなかったので、WookMarkに乗り換えました。
サーバサイド
さくらのVPSを借りて、Ruby on Railsで作りました。これは、2014年のDeveloper's SummitでWantedlyの仲さんの講演を聞いたのがきっかけです。当初一人でRailsをベースにWantedlyをローンチしたと聞いて、自分も一度やってみようと思った次第です。幸い、Railsに関する文献は多く、特に自分でカスタマイズすることもなく組み合わせるだけで、思ったサービスを作ることができました。ほんとに基本中基本しか触っていないという前提です。(先駆者の方恐るべしです)
COOKPADはWeb APIを公開していないため、スクレイピングOSSのNokogiriでレシピ情報をとってきました。
⬇参考サイト
http://morizyun.github.io/blog/ruby-nokogiri-scraping-tutorial/
取ってきたレシピ情報はDBに保存しています。初DB保存でした!
反省点
そもそも、全然人が来ないです(汗)
一日、新規ユーザ5〜10人のペース。。
肝心の奥さんは、このサービスに満足しているので最低限の目標は達成??かと。
やっぱりお金を稼ぎたいですね。
今回は勉強のためということもあり、どうやって儲けるかをあまり考えていなかったのですが、やはり最初にちょっとでも考えておくべきでした。次のサービスでは、「どう稼ぐか、どう集客するか、」を一番はじめに考えたいと思います。
COOKPADは売り上げの約50%が有料会員からもらっているというのは凄っす。
Bundler::GemNotFound: Could not find minitest-4.7.5.gem for installation
$rails new app $cd app $bundle install
すると、タイトルのエラーが。
$gem install minitest -v '4.7.5'
してもエラーはとれず。
$gem update bundler
でアップデートするといけました。
さくらのレンタルサーバを借りてみた
さくらのvpsの一番安いプランを契約してみた。
フレームワークはnode.jsとrailsのどちらかで迷ったけど、
ライブラリも充実しているrailsの方が早く作れると思い、railsをインストール。
#スクリプト言語の経験があまりないもんで、言語的ハードルはどちらも同じです。
$rails server
にてCould not find a JavaScript runtime. と怒られたけど、Gemfileに下記を追加すれば無事起動できました。
gem 'therubyracer' gem 'execjs'
参考:
Rails - Could not find a JavaScript runtime? - Stack Overflow
NS_ENUMとNS_OPTIONS
iOS 6 / Mac OS X 10.8からNS_ENUMとNS_OPTIONSが使えるようになった。
http://nshipster.com/ns_enum-ns_options/
使い分け方をまとめると、
- ビットマスクを使うとき : NS_OPTIONS
- それ以外 : NS_ENUM
■OKパターン
typedef NS_OPTIONS(NSUInteger, ESampleStateAnimal) { ESampleStateCat = 1 << 0, ESampleStateDog = 1 << 1, ESampleStateBird = 1 << 2, }; ESampleStateAnimal state = ESampleStateCat | ESampleStateDog;
【Objective-C デザインパターン】Prototypeパターン
Javaではよくデザインパターンの例文があるけど、そういえばObjective-Cではあんまりないなと。これを機会に本買って、Objective-Cのデザインパターンを勉強してみる。
Pro Objective-C Design Patterns for iOS
- 作者: Carlo Chung
- 出版社/メーカー: Apress
- 発売日: 2011/04/01
- メディア: Kindle版
- この商品を含むブログを見る
早速、Prototypeパターンについて振り返り。
[Prototypeパターンとは]
すでに存在するオブジェクトを複製することにより、新しいオブジェクトを生成する。
[利用するケース]
クラスからのインスタンス化が難しい場合。
newによる初期化にかなりの負荷がある場合。
[具体的には]
NSCopyingプロトコルのcopyWithZoneを実装することにより実現できる。
NSObjectクラスはcopyメソッドを持っているが、NSObjectプロトコルは持っていない。ただし、デフォルトではcopyメソッドは空なので、NSCopyingプロトコルをサポートしてcopyWithZoneを実装しなければいけない。
シャロウコピー、ディープコピーどちらにするかはケースバイケース。
ここでは、Productオブジェクトをプロトタイプとして作成。あとは、Productオブジェクトを量産したいときにcopyWithZoneを叩くのみ。
//
// Product.h
//
#import <Foundation/Foundation.h>
@interface Product : NSObject <NSCopying>
{
NSString *productName;
float price;
id delegate;
}
@end
//
// Product.m
//
#import "Product.h"
@implementation Product
- (id)copyWithZone:(NSZone *)zone
{
Product *copy = [[[self class] allocWithZone: zone]
initWithProductName:[self productName]
price:[self price]];
[copy setDelegate:[self delegate]];
return copy;
}
@end
特に、動的に生成が難しいCompositeパターンと併用するケースが有効みたい。またの機会に試したいですね。
calabash-androidの導入
Androidの受け入れテストのフレームワークを調べてみるとどうやらBDDでできるものがあるとのこと。
https://github.com/calabash/calabash-android
メリットとしては、
- 受け入れ基準を流行りのCucumber形式で書ける。
- 実機でもテスト可能。Jenkinsとの連携も可能。
- Javaで簡単にデフォルトにないステップを作成できる。
- 頻繁にpull requestが出されている。(2013/3/28現在)
- iOS版もあるので、マルチプラットフォーム開発にも使えそう。
デメリットは、
- リリースビルドされたapkファイルはテストできない。
インストール方法は簡単。以下のコマンドを実行すればインストールされる。
$sudo gem install calabash-android
ただし、以下の準備が必要なので要注意。
$calabash-android version
でcalabashのバージョンが表示されるとインストール完了。
テスト実行も簡単!
Androidプロジェクトのホームディレクトリ(AndroidManifest.xmlがあるディレクトリ)で
$calabash-android gen
と実行するとfeaturesフォルダが自動で作成される。featuresフォルダは以下の構成。
features
|_support
| |_app_installation_hooks.rb
| |_app_life_cycle_hooks.rb
| |_env.rb
|_step_definitions
| |_calabash_steps.rb
|_my_first.feature
あとは自分のテストしたいシナリオをmy_first.featureに書いた後、
$calabash-android run
<apk>
すればテストが実行される。この時にAndroidエミュレータが起動していること、もしくは実機が接続されていなければならない。また、デバッグビルドされたapkファイルしかテストできない。
# 本当なら受け入れテストはリリースビルドされたものに対して実施したいんだが、calabash-androidはどうやらAndroidのユニットテストフレームワークを裏で使っているようなのでそこは我慢。。
<apk>はテスト対象のapkファイルの相対パスとなる。例えばHoge.apkがbinフォルダにある場合、bin/Hoge.apkとなる。
ちなみに、htmlファイルにテスト結果を出力したい場合はオプションを指定する。
$calabash-android run
<apk> --format html --out reports.html
また、Cucumberのオプションもそのまま使用できるみたい。
例えば、タグ指定して特定のシナリオだけ実行したい場合は、
$calabash-android run
<apk> --tags @hoge