kamiのサービス制作ログ

ひとりでサービスを制作している人の作業ログ的なブログ

ITニュース専用の掲示板「89channel」を開発したときの記録

今日、ITニュースにコメントし合える掲示板サービス「89channel」をリリースしました。 Hack Channelと読みます。 ただのシャレです(´・ω・`)

この開発についてまとめてみました。

89channelとは

f:id:kami30k:20140707061555p:plain

89channelは、今話題のITニュースにコメントで議論できる掲示板サービスです。 Hacker Newsの日本版を目指してつくりました。 サービスの使い方についてはAboutをご覧ください。

Hacker Newsはユーザが記事をsubmitできますが、今回最初からこの機能をつけるとスパムの温床になるかなと危惧しました。 なので、現状は既存リソースから記事を定期取得するようしています。

今回、開発期間はrails newから10日間でのリリースでした。

開発環境

今回はRailsでサービスをつくりたかったので、Railsを採用しました。 Gemfileは記事のおわりにありますので、よかったら見てください。

開発ログ

権限管理はCanCanCanで

権限管理に、前から使ってみたかったCanCanを導入しました。 ただ、これはメンテナンスされておらず、Strong Parameters周りでうまく動作しません。

この後継としてCanCanCanがあるということがわかり、問題なく動作したのでこれを使いました。

デバッグ環境は超大事

これまで開発してきたサービスは、恥ずかしながらbetter_errorsのみを使ってブラウザでデバッグしてました。 今回は、デバッグに以下のgemを使いました。 それぞれの説明は省きますが、開発効率が何十倍になったんだろう……というくらい改善しました。

rails_best_practicesについては、愚直に従うのではなく、根拠を理解した上で、自分なりに採否を決め実装することが大事かなと思います。

group :development do
  gem 'pry-rails'
  gem 'pry-byebug'
  gem 'hirb'
  gem 'hirb-unicode'
  gem 'awesome_print'
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'quiet_assets'
  gem 'annotate'
  gem 'bullet'
  gem 'rails_best_practices'
end

文書はMarkdownで

AboutTerms of ServicePrivacy Policy各ページは、内部ではMarkdownで書いています。 これは、RedcarpetをGemfileに書きさえすれば、あとはHamlとして以下のように書けます。

:markdown

  本プライバシーポリシー(以下、「本ポリシー」と称します)は、ユーザが89channel(以下、「本サービス」と称します)を利用するにあたり、ユーザの情報を収集、利用する方法について説明するものです。
  本サービスを利用する場合、ユーザは、本ポリシーの記載に従い、ユーザ情報が収集、転送、操作、保存、開示およびその他の方法で利用されることに同意するものとします。

  ### 1. 情報の収集

  - 本サービスにユーザ登録を行なう場合、ユーザ名(任意)とパスワードを入力する必要があります。
  - 本サービスは、クッキーおよびこの類似技術を利用しており、本サービスはセッションクッキーおよび永続的なクッキーの両方を利用できるものとします。
  - 本サービスでは、ユーザが本サービスを利用することによって作成される情報(ログデータ)が自動的に記録されます。

Wheneverは有能

各記事には、今どれくらいホットかというトレンドポイントを持たせています。 このトレンドポイントは随時計算していると負荷が大きいと思ったので、cronで定期処理しています。 他にも、記事の取得やBackupを用いたバックアップにもcronを使っています。

このcronをRailsから簡単に使うgemがWheneverなのですが、これがまた大変便利です。 以下のようにconfig/schedule.rbに書くだけで、productionにデプロイ時によしなにやってくれます。

every 1.day, at: '00:00 am', roles: [:db] do
  rake 'backup:start'
end

サーバへのcrontabのインストールは忘れずに!

メンテナンスはCapistrano::Maintenanceで

メンテナンス用gemとして有名なものにTurnoutがあります。 これはRackミドルウェアとして動作し、tmp/maintenance.ymlの有無でメンテナンス中かどうかを判断します。 ただ、Capistranoでデプロイするとcurrent/tmp下に作られることになり、current/が指すreleaseディレクトリが変わると訳がわからなくなります。

Capistrano::Maintenanceはnginx側でpublic/下のファイルを静的に判断するので、運用者に分かりやすい作りなんじゃないかな、と思い採用しました。

turbolinksを無効にした

これは最後まで迷ったのですが、turbolinksを無効にしました。

今回Infinite ScrollSidrを採用したのですが、これがturbolinksと相性が悪いです。 具体的には、たとえば一度Infinite Scrollが発火すると、ページを遷移しても延々と裏でSQLを発行してしまいます。 恐ろしい……。

jQuery Turbolinksを入れても解決しなかったので、turbolinksを無効にしました。

おわりに

個人でサービスをつくるのはこれで4つ目になるのですが、自分の中での技術的なブレークスルーがあまりありませんでした。 複数人でサービスをつくってみたいのですが、無職なので難しいです。 次はマンネリを打破するためにNode.jsでサービスをつくってみます。

ご意見などあればTwitterまで連絡ください! お待ちしております。

おまけ:Gemfile

特にこれといったものは使っていませんが、公開してみます。

source 'https://rubygems.org'

gem 'rails', '4.1.1'

gem 'mysql2'

gem 'haml-rails'
gem 'sass-rails'
gem 'coffee-rails'

gem 'jquery-rails'
gem 'jbuilder'
gem 'uglifier'

gem 'bcrypt'

gem 'cancancan'  # 権限管理
gem 'redcarpet'  # Markdown パーサ
gem 'kaminari'   # ページング
gem 'paranoia'   # ユーザの論理削除
gem 'whenever'   # cron 処理
gem 'backup'     # MySQL のバックアップ

group :development do
  gem 'spring'                 # プリローダ(開発コマンド高速化)
  gem 'spring-commands-rspec'  # bin/rspec を生成
  gem 'capistrano'             # デプロイ
  gem 'capistrano-rails'
  gem 'capistrano-maintenance', github: 'capistrano/maintenance', require: false
                               # メンテナンス画面(要 nginx 設定)
  gem 'erb2haml'               # .erb を .haml に変換
  gem 'pry-rails'              # rails c を pry にする
  gem 'pry-byebug'             # ブレークポイントがつかえる
  gem 'hirb'                   # コンソール出力を整形する
  gem 'hirb-unicode'           # hirb のユニコード対応
  gem 'awesome_print'          # デバッグ出力を整形する ap コマンドを追加
  gem 'better_errors'          # エラー画面を見やすく表示
  gem 'binding_of_caller'      # エラー画面で REPL が使える
  gem 'quiet_assets'           # ログを整形
  gem 'annotate'               # model にスキーマ情報を付加
  gem 'bullet'                 # N+1 問題を検知
  gem 'rails_best_practices'   # コードチェック
end

group :development, :test do
  gem 'rspec-rails'
  gem 'capybara'
  gem 'poltergeist'
  gem 'factory_girl'
  gem 'database_cleaner'
  gem 'shoulda-matchers', require: false  # RSpecにマッチャを追加
end

group :production do
  gem 'therubyracer'
  gem 'unicorn'
end