active_decorator のdecoratorをrspecでテストする方法
active_decorator は便利なのですが、rspecでテストが上手く書けなくて、書き方を調べていた。
ただ、web上に情報が無く・・・
あ…ありのまま 今 起こった事を話すぜ!
「おれは decoratorのspecを書こうとしていたと
思ったら いつのまにかactive_decorator, rspec-rails, rails のソースコードを読んでいた」
decorator のspecを書けるように色々と設定する
そのままだとspecが上手く書けないので、設定を追加しテストを書きやすくする。
application.rb でlib/のファイルを自動で読み込むようにする
config/application.rb の
# config.autoload_paths += %W(#{config.root}/extras)
こんな感じでコメントアウトされている所を
config.autoload_paths += %W(#{config.root}/lib)
に変更して、lib/ を読み込むようにする。*1
rspecのexample groupを追加する
spec/decorators/*.rb に対応するgroupを追加する。
lib/rspec/rails/example/decorator_example_group.rb
module RSpec::Rails module DecoratorExampleGroup extend ActiveSupport::Concern include RSpec::Rails::RailsExampleGroup include ActionView::TestCase::Behavior def decorate(obj) ActiveDecorator::Decorator.instance.decorate(obj) obj end included do metadata[:type] = :decorator before do ActiveDecorator::ViewContext.current = controller.view_context end end end end
spec_helper.rb でdecoratorの設定を追加する
spec/spec_helper.rb
RSpec.configure do |config| # for active_decorator require 'rspec/rails/example/decorator_example_group' config.include RSpec::Rails::DecoratorExampleGroup, :type => :decorator, :example_group => { :file_path => config.escaped_path(%w[spec decorators]) } end
使い方の例
active_decorator のExamplesのコードに対応したspecを書いてみる。
app/decorators/user_decorator.rb
# app/decorators/user_decorator.rb module UserDecorator def full_name "#{first_name} #{last_name}" end def link link_to full_name, website end end
spec/decorators/user_decorator_spec.rb
describe UserDecorator do before do @user = User.create(first_name: 'sinsoku', last_name: 'listy', website: 'http://d.hatena.ne.jp/sinsoku') end subject { decorate @user } its(:full_name) { should eq 'sinsoku listy' } its(:link) { should eq '<a href="http://d.hatena.ne.jp/sinsoku">sinsoku listy</a>' } end
実行結果
$ rspec spec/decorators/ UserDecorator link should eq "<a href=\"http://d.hatena.ne.jp/sinsoku\">sinsoku listy</a>" full_name should eq "sinsoku listy" Finished in 0.07222 seconds 2 examples, 0 failures
追記
sinsoku/active_decorator at support_rspec https://github.com/sinsoku/active_decorator/tree/support_rspec
github でforkしてみた。
forkしたやつはspec_helper.rb に「require 'active_decorator/rspec'」を書くだけで済むようになってる
*1:decorator_example_group.rb が require さえ出来れば、どこに置いても問題ない
Gruffをruby1.9.3 + Railsで動くようにする
ruby 1.9.3 だとZeroDivisionErrorで動かなかったので、動く方法を調べた
参考ページ
- GruffがZeroDivisionErrorで動かない - 発声練習 http://d.hatena.ne.jp/next49/20120516/p2
解決方法
ググったら解決方法は色々と出てくるけど「gemのソースを直接変更する」は微妙なので、alias_method_chainで直すようにした。
# config/initializers/gruff/base.rb module Gruff class Base def label_with_ruby193(value) if @marker_count.to_f == 0 label = value.to_i.to_s parts = label.split('.') parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{THOUSAND_SEPARATOR}") parts.join('.') else label_without_ruby193(value) end end alias_method_chain :label, :ruby193 end end
Railsで複数データベースを扱えるBanana
初めてgemを作って、RubyGems.orgで公開してみました。
ソースはGithubに置いてあります。
これは何?
1つのrailsアプリで複数データベースのマイグレーションを実行できるようにするgemです。
gem入れて、設定しておけば普段どおり rake db:create, rake db:migrate, rake db:drop が使えます。
インストール方法
gemなので、Gemfileに書いてbundle installするか、gem installで入ります。
Gemfile
gem 'banana'
もしくは
$ gem install banana
使い方
config/database.yml にdatabaseの設定を追加し、model/migrationに接続先の情報を書きます。
接続先の情報は /#{Rails.env}$/ になるような名前にして下さい。
例
config/database.yml
default: &default adapter: mysql2 encoding: utf8 reconnect: false pool: 5 username: root password: socket: /var/run/mysqld/mysqld.sock development: <<: *default database: fruit_development test: <<: *default database: fruit_test production: <<: *default database: fruit_production vegetable_development: <<: *default database: vegetable_development vegetable_test: <<: *default database: vegetable_test vegetable_production: <<: *default database: vegetable_production
app/models/vegetable.rb
class Vegetable < ActiveRecord::Base establish_connection "vegetable_#{Rails.env}" end
app/models/onion.rb
class Onion < Vegetable end
db/migrate/20120728121720_create_onions.rb
class CreateOnions < ActiveRecord::Migration DATABASE_NAME = "vegetable_#{Rails.env}" def change create_table :onions do |t| t.timestamps end end end
縛りプレイで勉強するGitの基礎
縛りプレイをすることで、Gitの基礎であるハッシュ(sha-1)を意識してみる。
縛りプレイ とは
1. SMプレイのうち亀甲縛りなど縄を使うプレイ(性行為)のこと。昭和から存在する言葉。 2. ゲームをプレイする際、本来ゲーム側からは設定されていない制限(縛り)を自ら科す事によって、より難易度の高いゲームをプレイする事。
記事のタイトルの意味は 2. の方です。
概要
縛りの条件は下記の通り。
つまり、リモート(origin含む)、ブランチ(master含む)、タグの使用禁止です。
関連して、下記のコマンド/操作も使用禁止です。
- git clone (origin が作成されるため)
- git checkout -b (-b オプションはブランチ作られるので禁止、それ以外はOK)
- git pull (動作が複雑なので)
- .git/ の直接編集(邪道なので)
つまり、常にdetached HEADで開発し、sha-1ハッシュをノートにメモしながら開発することになります。
これにより、「Gitの基礎であるハッシュ(sha-1)がどういうものか?」というのが分かります。*1
この記事には、cloneとか、pullみたいな上級者用のコマンドは登場しません。
Gitリポジトリの準備
まずはgitリポジトリを用意する必要があります。
$ mkdir git_proj $ cd git_proj $ git init
masterなんてブランチは不要なので、削除します。ただ、すぐに削除が出来ないため、空のコミットを作成し、その後にmasterブランチを削除します。
$ git commit --allow-empty -m "first commit" $ git log -n 1 (表示されたsha-1の値をノートにメモする) $ git checkout <メモしたsha-1> $ git branch -d master
ファイルの追加/コミットの手順
基本的に普通のadd/commitと同じです。
例
新しいファイルを作成して、追加した場合のコマンドなどを記載してみました。
$ echo "Hello, Git World" > README.md $ git add README.md $ git commit -m "add README"
コミット毎にノートにsha-1の値をメモしておいた方が良いです。(ブランチが使えないので)
$ git log commit 421bcacadf8581e8cc459ea1254ee3990af967af Author: sinsoku <sinsoku.listy@gmail.com> Date: Wed Jul 18 00:07:49 2012 +0900 add README commit 62f92f671d0e83d8a75fabd1dd46f64aa7b36dc6 Author: sinsoku <sinsoku.listy@gmail.com> Date: Tue Jul 17 23:59:08 2012 +0900 first commit sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(421bcac...)) $
ファイルを変更したコミットを作ってみる。
markdown形式にREADME.mdを変更してみました。
$ echo "# Hello, Git World" > README.md $ git add README.md $ git commit -m "markdown形式に直した"
ログを確認してみる。
$ git log -n 1 commit 1a8905309eac98743b3b2facd30db992ff0d5b9e Author: sinsoku <sinsoku.listy@gmail.com> Date: Wed Jul 18 00:15:44 2012 +0900 markdown形式に直した
私の環境では、このような出力になりました。
sha-1の値は環境により異なりますが、大体の表示は同じになると思います。
ブランチ関連
branchコマンドを使わなくても、sha-1をcheckoutしてコミットをする事で自然にログが分岐します。
例
まず「add README」のsha-1の値をcheckoutしてみます。
(この値は各人で異なるので、自分の環境の値を使う)
$ git checkout 421bcacadf8581e8cc459ea1254ee3990af967af Warning: you are leaving 3 commits behind, not connected to any of your branches: 1a89053 markdown形式に直した 421bcac add README 62f92f6 first commit If you want to keep them by creating a new branch, this may be a good time to do so with: git branch new_branch_name 1a8905309eac98743b3b2facd30db992ff0d5b9e HEAD is now at 421bcac... add README sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(421bcac...)) $
警告が出ていますが、気にせずに作業します。
README.md は作られているので、Licenseのファイルでも作成してみましょう。
$ touch LGPL-2.1 $ git add LGPL-2.1 $ git commit -m "add License"
ログを確認しましょう。
$ git log commit 1aeb413b6d839d85074cc0e3f5fee9f1dfe16252 Author: sinsoku <sinsoku.listy@gmail.com> Date: Wed Jul 18 00:29:18 2012 +0900 add License commit 421bcacadf8581e8cc459ea1254ee3990af967af Author: sinsoku <sinsoku.listy@gmail.com> Date: Wed Jul 18 00:07:49 2012 +0900 add README commit 62f92f671d0e83d8a75fabd1dd46f64aa7b36dc6 Author: sinsoku <sinsoku.listy@gmail.com> Date: Tue Jul 17 23:59:08 2012 +0900 first commit sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(1aeb413...)) $
「add License」のコミットは「add README」の次に作成されました。
現在の状態の詳細をlogのオプションを使って表示してみます。
$ git log --oneline --graph --decorate 1a8905309eac98743b3b2facd30db992ff0d5b9e 1aeb413b6d839d85074cc0e3f5fee9f1dfe16252 * 1aeb413 (HEAD) add License | * 1a89053 markdown形式に直した |/ * 421bcac add README * 62f92f6 first commit sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(1aeb413...)) $
上記のようにブランチが出来ています。
では、これをマージします。
$ git merge 1a8905309eac98743b3b2facd30db992ff0d5b9e Merge made by the 'recursive' strategy. README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(9e97a14...)) $
グラフ表示でログを確認してみます。
$ git log --oneline --graph --decorate * 9e97a14 (HEAD) Merge commit '1a8905309eac98743b3b2facd30db992ff0d5b9e' into HEAD |\ | * 1a89053 markdown形式に直した * | 1aeb413 add License |/ * 421bcac add README * 62f92f6 first commit sinsoku@sinsoku-vm:~/Projects/sample/git_proj(git:(9e97a14...)) $
ちゃんとマージされています。
リモートにブランチをpush
remoteコマンドやbranchコマンドが使えないため、
例
$ git push git@github.com:sinsoku/git_proj.git 9e97a14:refs/heads/develop
これで、リモートリポジトリにdevelopブランチが作成されます。
リモートにタグをpush
これはブランチとほとんど同じです。
例
$ git push git@github.com:sinsoku/git_proj.git 9e97a14:refs/tags/v1.0.0
リモートの変更を取り込む
clone, pullが使えず、branchも使えないため、fetchを使います。
取り込んだ変更個所の指定は常にsha-1を使います。
例
例として、gitのリポジトリの変更を取り込んでみます。
$ mkdir git $ cd git $ git init $ git fetch git://github.com/git/git.git
github上で確認すると、タグ v1.7.11.2 のハッシュタグは 8d141a1d562abb31f27f599dbf6e10a6c06ed73e のようです。
$ git log 8d141a1d562abb31f27f599dbf6e10a6c06ed73e commit 8d141a1d562abb31f27f599dbf6e10a6c06ed73e Author: Junio C Hamano <gitster@pobox.com> Date: Wed Jul 11 12:55:38 2012 -0700 Git 1.7.11.2 Signed-off-by: Junio C Hamano <gitster@pobox.com> commit b700086d840ceaee339f9f031be72b34e237f84f Merge: 2e1e8ef b31272f Author: Junio C Hamano <gitster@pobox.com> Date: Wed Jul 11 12:58:28 2012 -0700 Merge branch 'jc/maint-blame-unique-abbrev' into maint "git blame" did not try to make sure that the abbreviated commit object names in its output are unique. * jc/maint-blame-unique-abbrev: blame: compute abbreviation width that ensures uniqueness
上記のように、ログが表示されています(=変更が取得できています)。
参考書籍
- 作者: 濱野純(Junio C Hamano)
- 出版社/メーカー: 秀和システム
- 発売日: 2009/09/24
- メディア: 単行本
- 購入: 31人 クリック: 736回
- この商品を含むブログ (155件) を見る
- 作者: 岡本隆史,武田健太郎,相良幸範
- 出版社/メーカー: 技術評論社
- 発売日: 2012/07/10
- メディア: 単行本(ソフトカバー)
- 購入: 7人 クリック: 103回
- この商品を含むブログ (26件) を見る
後日談
この記事の話を隣の人に話したら「努力の方向性が間違っている」と言われました(´・ω・)
*1:たぶん
Ubuntu 12.04でEmacs24を入れる
備忘録。
$ add-apt-repository ppa:cassou/emacs $ apt-get update $ apt-get install emacs-snapshot
参考にしたページ
railsを少しずつ勉強する - 2. シンプルなブログ
前の記事の続きです。
シンプルなブログwebアプリを作成していきたいと思います。
シンプルなブログ の仕様
- 記事を新規作成、編集、削除ができる
- 記事に対して、コメントを新規作成、編集、削除ができる
モデルの設計
ブログ記事とコメントのモデルを設計してみます。
まずはCacooで設計などをしておき、必要な属性や関連などを洗い出す。
こんな感じ。
次に英語に直します。
もし英単語が分からない場合はgoo辞書などで調べると良いです。
記事のモデル
Article - title - body
コメントのモデル
Comment - article_id - body
railsのアプリ作成
railsでアプリを作成します。"sinsoku-blog"がアプリの名前になります。
- -T はデフォルトのTest::Unitを使わないようにします。RSpecを使うので、指定しています。
- --skip-bundle はアプリ作成後のbundle installを抑止します。
$ rails new sinsoku-blog -T --skip-bundle
Gemfileを編集します
Gemfileにはアプリで使用するrubyライブラリ(gem)が書かれています。
このファイルを追記・修正します。
- "therubyracer" はCoffeeScript関連で必要になるため、コメントアウトになっているのを外します
- "rspec-rails" はテストでRSpecを使うため、追加します
Gemfile
@@ -15,7 +15,7 @@ group :assets do gem 'coffee-rails', '~> 3.2.1' # See https://github.com/sstephenson/execjs#readme for more supported ru - # gem 'therubyracer', :platforms => :ruby + gem 'therubyracer', :platforms => :ruby gem 'uglifier', '>= 1.0.3' end @@ -36,3 +36,7 @@ gem 'jquery-rails' # To use debugger # gem 'debugger' + +group :test, :development do + gem 'rspec-rails' +end
変更後、bundlerでgemをインストールします。
$ bundle install --path vendor/bundle
railsのscaffold
rails generator(gに省略可)を使い、RESTful*2になるようなMVC(Model,View,Controller)の各ファイルを生成することができます。
$ rails g scaffold Article title:string body:text
$ rails g scaffold Comment article:belongs_to body:text
テーブルの作成
まだDBにテーブルが作成されていないため、テーブルを作成します。
データベースを作成
$ bundle exec rake db:create
マイグレーションを実行
$ bundle exec rake db:migrate
簡単な動作確認
rails server(sに省略可)を使い、サーバを立ち上げてみます。
$ rails s
サーバ起動後、http://localhost:3000/articles にアクセスすると、記事のページが表示されます。
関連(belongs_to)の所のview修正
belongs_to のあるモデルをscaffoldで作成しても、Commentの新規作成の所でエラーが発生してしまいます。
これを修正します。
app/models/comment.rb
@@ -1,4 +1,4 @@ class Comment < ActiveRecord::Base belongs_to :article - attr_accessible :body + attr_accessible :body, :article_id end
app/views/comments/_form.html.erb
@@ -12,8 +12,8 @@ <% end %> <div class="field"> - <%= f.label :article %><br /> - <%= f.text_field :article %> + <%= f.label :article_id %><br /> + <%= f.text_field :article_id %> </div> <div class="field"> <%= f.label :body %><br />
これで記事のidを入力することで、記事とコメントを紐付ける事ができるようになります。
twitter-bootstrap-railsで画面を整える
twitter-bootstrap-railsを使います。
GithubのREADMEに従って、インストール・セットアップをする。
Gemfileにgemを追加する
Gemfile
@@ -40,3 +40,5 @@ gem 'jquery-rails' group :test, :development do gem 'rspec-rails' end + +gem "twitter-bootstrap-rails"
そして、インストール。
$ bundle install
bootstrapに必要なファイルを生成する
$ rails g bootstrap:install
$ rails g bootstrap:layout application fluid
- fixed: 画面の大きさ固定。
- fluid: 画面の大きさ可変。スマホっぽい画面になります。
ナビゲーションバー、サイドバーの修正
自動生成されたナビゲーションバー、サイドバーを修正する。
app/views/layouts/application.html.erb
@@ -31,9 +31,8 @@ <a class="brand" href="#">SinsokuBlog</a> <div class="container nav-collapse"> <ul class="nav"> - <li><%= link_to "Link1", "/path1" %></li> - <li><%= link_to "Link2", "/path2" %></li> - <li><%= link_to "Link3", "/path3" %></li> + <li><%= link_to "記事一覧", "/articles" %></li> + <li><%= link_to "コメント一覧", "/comments" %></li> </ul> </div><!--/.nav-collapse --> </div> @@ -51,9 +50,8 @@ <h3>Sidebar</h3> <ul class="nav nav-list"> <li class="nav-header">Sidebar</li> - <li><%= link_to "Link1", "/path1" %></li> - <li><%= link_to "Link2", "/path2" %></li> - <li><%= link_to "Link3", "/path3" %></li> + <li><%= link_to "記事一覧", "/articles" %></li> + <li><%= link_to "コメント一覧", "/comments" %></li> </ul> </div><!--/.well --> </div><!--/span-->
コメントを記事の下に表示する
記事とコメントが別の画面に表示されても微妙ですので、同じ画面に表示されるようにします。
app/views/articles/show.html.erb
@@ -10,6 +10,12 @@ <dd><%= @article.body %></dd> </dl> +<ul> + <% @article.comments.each do |comment| %> + <li><%= comment.body %></li> + <% end %> +</ul> + <div class="form-actions"> <%= link_to t('.back', :default => t("helpers.links.back")), articles_path, :class => 'btn' %>
railsを少しずつ勉強する - 1.1. 環境構築(追記)
前回の記事の続き。書き忘れがあったので。。。
Ubuntuのホームディレクトリのフォルダ名を英語にする
$ LANG=C xdg-user-dirs-gtk-update
これで「ダウンロード」のフォルダ名が「Downloads」のように変更されます。
VMware Tools のインストール
VMware Playerのメニューから「仮想マシン」→「VMware Toolsのインストール」をクリックする。
CDがマウントされるので、そのCD内のファイルを解凍する。
コマンドプロンプトを開き、解凍したディレクトリまでcdで移動し、vmware-install.pl を実行する。
設定は特に問題なければ、デフォルトのままで[Enter]で大丈夫だと思います。
$ sudo ./vmware-install.pl
これで、ホストOS/ゲストOSの間でクリップボードの共有、ファイルのコピペ、ファイルのD&Dなどが出来るようになります。
gitの初期設定
ユーザ名、メールアドレス、色などを設定する。
$ git config --global user.name "sinsoku" $ git config --global user.email "sinsoku.listy[at]gmail.com" $ git config --global color.ui auto