heroku+sinatra+activerecord+postgresql
ローカルでの準備
環境
- Vigrant with CentOS6.4
- ruby 2.0~
- postgresql9.3
postgresql のインストール
"PostgreSQL Deep Dive: VagrantでPostgreSQL 9.3の動く仮想サーバを自動構築してみる (http://pgsqldeepdive.blogspot.jp/2013/09/vagrant-postgresql93.html)"のとおりにインストール。
データベースの作成
使用する database を作ります。
% sudo -u postgres -i $ psql =# create database testdb; =# \q
次にtableを postgresql で作ります。データベースは .env で指定し、model.rb でdotenv gem を使って読み込ませます。
% vi .env DATABASE_URL = "postgres://localhost/testdb" % vi model.rb require 'dotenv' require 'active_record' Dotenv.load ActiveRecord::Base.establish_connection(ENV['DATABASE_URL']) class Post < ActiveRecord::Base; end
Rakefileではそれを require します:
% vi Rakefile require 'sinatra/activerecord' require 'sinatra/activerecord/rake' require 'rake/clean' require './model'
migration ファイルを作り、migrate をかけテーブルを作成します:
% rake db:create_migration NAME=create_posts .... % vi db/migration/xxxxx_create_posts.rb class CreatePosts < ActiveRecord::Migration def change create_table :posts do |t| t.string :text t.timestamps end end end % rake db:migrate ...
これでローカル上のデータベース作成は完了。念のため確認します:
% psql testdb testdb=> \dt List of relations Schema | Name | Type | Owner --------+-------------------+-------+--------- public | posts | table | vagrant public | schema_migrations | table | vagrant (2 rows) => select * from posts; id | text | created_at | updated_at ----+----------+----------------------------+---------------------------- => \q
ウェブアプリの作成
'localhost:port/' にアクセスされると text: "hoge" なレコードを一つ追加していく簡単なsinatraアプリを作ります。
まずGemfile に使う gem を羅列し、bundler install して Gemfile.lock を作ります。
% vi Gemfile source 'https://rubygems.org' gem 'rake' gem 'sinatra' gem 'sinatra-contrib' gem 'sinatra-activerecord', :require => 'sinatra/activerecord' gem 'dotenv' gem 'activerecord' gem 'pg' % bundle install ...
アプリ本体。こちらをまず先に require 'xxx' 形式で書いてから Gemfile に構成しなおしてもかまいません。
% vi app.rb require 'bundler' Bundler.require require './model' class MyApp < Sinatra::Base configure :development do register Sinatra::Reloader set :bind, '0.0.0.0' end get '/' do Post.create(text: "hoge") erb :show end end __END__ @@show count: <%= Post.count.to_s %> <div> <% Post.all.each do |post| %> <%= post.text %><br> <% end %>
後は普通に config.ru を書き、rackup し、ブラウザ等で確認します:
% vi config.ru require './app' run MyApp % bundle exec rackup & .... % lynx losthost:9292
foreman 起動用ファイルの作成
% vi Procfile web: bundle exec rackup -p $PORT % foreman start & 17:38:52 web.1 | started with pid 3530 .... % curl losthost:5000
サーバーへのデプロイ
バックアップファイルなどをキレイにするため rake clean をかけ、 また.env はサーバー上に置くと変なことになるので gitignore しときます。
% rake clean % vi .gitignore .env
いつもどおりに:
% git init; git add . ; git commit -m init -a % heroku create NAME ...
heroku-postgresql の addon を使います。後は通常の手順です。
% heroku addons:add heroku-postgresql ... % heroku run rake db:migrate ... % git push heroku master ... % heroku ps web.1: up 2014/MM/DD xx:xx:xx (~ 1m ago) % heroku open ....
Tips
restart
データベースをrollback, migrate したりすると停止したりするので restart をかけます。
% heroku ps:restart web Restarting web dynos... done
ローカルからサーバーのデータベースにアクセス
% heroku config して表示される DATABASE_URL の値を .env に入れます。
% heroku config DATABASE_URL: postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename HEROKU_POSTGRESQL_XXXX_URL: postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename LANG: en_US.UTF-8 RACK_ENV: production % vi .env #DATABASE_URL = "postgres://localhost/testdb" DATABASE_URL = "postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename"
参考
ntp で時刻を合わせないと omniauth-twitter で 401食らう件
他のアプリでふつーに使ってたのになんか動かなくなった。 dev.twitter.com で callback ちゃんと入れてるしなあ、と思ってぐぐってたr:
gem 'omniauth-twitter'で認証しようとしてOAuth::Unauthorized 401 Unauthorizedなんてエラーがでたら - Qiita : http://qiita.com/hirokishirai/items/5a43977a38ecd922bfb9
確かに virtual pc 上で 20分ぐらい遅れてた。
http://qiita.com/tsu_nera/items/9be676b04b190e45b281 のとおり ntp いれて時刻合わせたらうまく動いた。
padorina で will_paginateを bootstrap と使う
will_paginate
https://github.com/mislav/will_paginate/ にあるとおりインストールその他。
% padrino g plugin will_paginate
bootstrap と合わせるには、https://gist.github.com/phildionne/5785087 を lib/will_paginate_bootstrap_renderer.rb あたりにセーブして、config/boot.rb で require する。
% vi app/controllers/entry.rb ... entries = Entry.paginate(page: params[:page], per_page: 5).order("created_at desc") content_for(:pagination, will_paginate(entries, renderer: WillPaginate::ViewHelpers::BoostrapLinkRenderer, previous_label: "«", next_label: "»")) haml :index, locals: {entries: entries} ... % vi app/views/index.haml - entries.each do |entry| = haml :show, :layout => false, locals: {entry: entry} = yield_content(:pagination)
とかしてあげる。
参考
Ruby - padrino+will_paginate+bootstrap向けにカスタムレンダラを実装 - Qiita : http://qiita.com/insight3110/items/d513aeaeac32552c3c9a
ただしここの最後にある変更はする必要がない。
padrino で自分の config
padrino で自分の config
YML app own config · padrino/padrino-framework Wiki GitHub : https://github.com/padrino/padrino-framework/wiki/YML-app-own-config
あたりを見ながら。
% vi config/config.yaml :twitter: :consumer_key: "xxxx" :consumer_secret: "xxxx" % vi config/apps.rb Padrino.configure_apps do ... begin set :config, YAML.load(open(Padrino.root("/config/config.yaml")).read) rescue logger.fatal("cannot open config file: /config/config.yaml") exit end end
としとくと、どこでも settings.config[:twitter][:consumer_key] と拾える。
padrino tips
padrino tips
rspec で test
準備
g project するときに -t rspec すると rspec がすぐ使える。
database へのアクセス
test 環境で migrate しないと table がないと怒られます。
% rake ar:migrate RACK_ENV=test
post
it do の中でpost "/post" して last_response 拾おうとしても、403 が帰ってきちゃいます。 form_tag() 使うなどして token 渡さないと csrf で蹴られちゃうんですね。 テスト環境では外しちゃってもいいかも?
configure :test do set :protect_from_csrf, false end
textarea の行頭空白
.panel-body = form_for(:foo) do |f| %div.form-group = f.text_field(:name) %div.form-group = f.text_area(:content, cols: 80, rows: 20)
とかすると行頭の空白の扱いが変なので、text_area のとこの = を ~ に変えるとうまくいく。
表示させるときも、
.panel-body~ @page.formatted_content.html_safe
のように ~ を使う。
ソースを読む
g admin_map してできた models/pages.rb, views/pages/* とか読むとためになるかも。
splat
sinatra の時見たく get '/*' do だと params[:splat] に入ってくんない。 どうやら get '/*splat' としてあげないとダメなようだ。
gollum インストールメモ
gollum インストールメモ
インストール
% sudo gem install すると iculib がないと怒られるので、 % yum list | grep icu して出てくる libicu-devel を入れてから再度入れなおす。
% yum install libicu-devel ... % sudo gem install gollum ...
起動
init して server を立ち上げます。
% mkdir wiki; cd wiki % git init % gollum
gollum-lib
エンジン部は別なので、このライブラリをバックエンドに使っていじくるのもいいのかも。 gollum/gollum-lib · GitHub : https://github.com/gollum/gollum-lib
参考サイト
- gollumを使って個人用wikiをサーバに立てた | blog: takahiro okumura : http://blog.hifumi.info/2014/02/02/my-wiki-powered-by-gollum/
- githubのwikiエンジン"gollum"の導入と細かい設定 - yukke::note : http://yukke.hateblo.jp/entry/2013/05/02/224859
- RubyでWikiをはじめる〜gollum | Scimpr Blog : http://blog.scimpr.com/2014/01/31/ruby%E3%81%A7wiki%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%80%9Cgollum/
padrino でのウェブサービス作りを実況してみる
padrino でのウェブサービス作りを実況してみる
概要
twitter で書きなぐったのをまとめてブログとかwikiとかshortnote にあげる
まずはプロジェクトとか
プロジェクト名は、"timeline_editor"。安易ですね。
% pwd /home/source % padrino g project timeline_editor -d activerecord -e erb -s jquery -t rspec .... % cd timeline_editor % vi app/app.rb module TimelineEditor class App < Padrino::Application ... get :index, map: "/" do erb "hello world" end end
レイアウト
bootstrap 使って見てくれを整えます。
% vi app/views/layouts/application.erb <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script> <script type="text/javascript" src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script> <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="navbar navbar-default"> <ul class="nav navbar-nav"> <li><a href="/">top</a></li> </ul> </div> <div class="container"> <div class="panel panel-primary"> <div class="panel-heading">title</div> <div class="panel-body"><%= yield %></div> </div> <div class="panel panel-primary"> <div class="panel-heading">ENV</div> <div class="panel-body"> <div><h2>env</h2><%= h env.inspect %></div> </div> </div> </div> </body> </html>
bootstrap は後ほど取り上げるけど、ソレっぽく見てくれを整えてくれる。 ナビゲーションバーを上に、中身を "panel" で包むと見やすい。
timeline を表示させる
gem の twitter を使おう。consumer key/secret は取っておいてね。
% vi Gemfile ... gem 'twitter' % bundle ...
% vi app/app.rb get :user_timeline do twitter = Twitter::REST::Client.new do |config| config.consumer_key = "xxx" config.consumer_secret = "xxx" config.access_token = "xxx" config.access_token_secret = "xxx" end timeline = twitter.user_timeline(count: 50) erb timeline.map {|status| status.text }.inspect end
key や token の類はとりあえず決め打ちにします。config化や認証は後で。 inspect して status が取れてるか確認。 そしたら view を使ってみる。
% vi app/app.rb get :user_timeline do ... timeline = twitter.user_timeline(count: 50) erb partial 'status', :collection => timeline ... % vi app/views/_status.erb <li><%= h status.text %></li>
partial template を使います。対象オブジェクトの配列をcollection で渡して view で "_" から始まるテンプレートファイルを作って partial を呼ぶと、配列回してくれるらしいです。便利ですね。