Sinatraでmongoidを使う（herokuでの公開も）




概要
====================

サンプル：http://mongoid-to-be-used-in-sinatra.herokuapp.com/
ソース：https://github.com/k-ta-yamada/mongoid-to-be-used-in-sinatra

Sinatraにてmongoidを使ってMongoDBに接続を行う。
さらにherokuへデプロイし、アドオンとしてMongoHQを使ってみる。

作成するクラスはPostクラスとそれに含まれるCommentクラス。
上記はMongoDBでは下記のようになる。

```json
> db.post.find().pretty()
{
	"_id" : ObjectId("542ce0296b6579b201000000"),
	"title" : "Lorem ipsum",
	"article" : "Lorem ipsum dolor sit amet ...",
	"comments" : [
		{
			"_id" : ObjectId("542ce0296b6579b201010000"),
			"name" : "test_name0",
			"comment" : "comment comment"
		},
		{
			"_id" : ObjectId("542ce0296b6579b201020000"),
			"name" : "test_name1",
			"comment" : "comment comment"
		},
		{
			"_id" : ObjectId("542ce0296b6579b201030000"),
			"name" : "test_name2",
			"comment" : "comment comment"
		}
	]
}
```



使用するgem
====================

- 必須
	- sinatra
	- mongoid
- おまけ
	- slim
		- slimテンプレート用。erb使うならば別にいらない。
	- sinatra-contrib
		- sinatra/reloaderを使用


準備
====================

```
mkdir mongoid-to-be-used-in-sinatra
cd mongoid-to-be-used-in-sinatra
git init
bundle init
```



Gemfileの編集
====================

`bundle init`で作成された`./Gemfile`を下記のように編集。

```./Gemfile
source 'https://rubygems.org'

gem 'sinatra'
gem 'slim'
gem 'mongoid'

group :development do
  gem 'sinatra-contrib'
end

```
上記のように編集後、下記を実行（あとでアプリ起動するときでもいいけど）。
`bundle install --path vendor/bundle`



mongoidの設定ファイル作成
====================

`./mongoid.yml`を作成し、下記のように編集。

```yml
development:
  sessions:
    default:
      database: mongoid
      hosts:
        - localhost:27017
production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>
```

とりあえずdevelopmentとproductionの２つの環境の設定のみ。
developmentはローカル環境で、productionはherokuでの使用を想定。
ローカルで試すだけならばproductionは不要。
上記のファイルをアプリにてMongoid.load!にて読み込む。



アプリケーションの作成
====================

`./app.rb`を作成して編集。お好みに合わせて作成すればよいかと。
ポイントは下記

- Mongoid.load!で設定ファイル(mongoid.yml)を読み込む
- 各クラスにて`include Mongoid::Document`する

```ruby
require 'sinatra'
require 'sinatra/reloader' if development?
require 'slim'
require 'mongoid'
Mongoid.load!('./mongoid.yml')

# ##############################
# Mongoid Document Section
# ##############################
class Post
  include Mongoid::Document
  field :title,   type: String
  field :article, type: String
  embeds_many :comments
end

class Comment
  include Mongoid::Document
  field :name
  field :comment
  embedded_in :post
end

# ##############################
# Constants
# ##############################
AFTER_ROUTING_MATCHER = /\/\w+/
BOOTSTRAP_CDN = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'
LOREM_IPSUM = <<EOF
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
EOF

# ##############################
# Routing Section
# ##############################
after AFTER_ROUTING_MATCHER do
  redirect to('/')
end

get '/' do
  slim :index, locals: { posts: Post.all }
end

get '/create' do
  redirect to('/') if Post.count >= 10
  # create new Post
  post = Post.create(title: 'Lorem ipsum',
                     article: LOREM_IPSUM)
  # create comment of embedded in Post
  3.times do |i|
    post.comments.create(name: "test_name#{i}",
                         comment: 'comment comment')
  end
end

get '/delete_all' do
  Post.delete_all
end

# ##############################
# Template Section
# ##############################
__END__

@@layout
html
  head
    <!-- Latest compiled and minified CSS -->
    link rel="stylesheet" href=BOOTSTRAP_CDN
    style
      | body { padding-top: 50px; }
      | ul.nav { background-color: #FFF; }
  body
    ul.nav.nav-tabs.nav-justified.navbar-fixed-top
      li
        a href='/' index
      li
        a href='/create' create
      li
        a href='/delete_all' delete_all
    .container
      p Post.count=[#{Post.count}]
      == yield

@@index
- posts.all.each do |post|
  h2 = post.title
  p = post.article
  - post.comments.each do |comment|
    p
      | #{comment.name}
      br
      | #{comment.comment}
```

上記保存後アプリ実行の前に`mongod`にてMongoDBを起動しておき、
`bundle exec ruby app.rb`で実行。
> mongodとかはMongoDBのインストール記事とかを探してください。


その他
====================

## mongoid.ymlのproductionにMongoHQを設定する

herokuにてMongoHQのアドオンを追加。
のち、herokuのConfig Variablesに`MONGOHQ_URL`が設定されたことを確認。
あとは上記記載のようにmongoid.ymlに設定する。