Ruby 簡単なテスト駆動開発とリファクタリング
テスト駆動開発とリファクタリングを行いました
重要なとこをまとめてみました
まず静的なページに対する結合テスト(request spec) を生成します
$ rails generate integration_test static_pages invoke rspec create spec/requests/static_pages_spec.rb
static_pages_spec.rbが生成されました
中身はこんな感じになっていて
require 'spec_helper' describe "Static pages" do describe "Home page" do it "should have the content 'Sample App'" do visit '/static_pages/home' expect(page).to have_content('Sample App') end end end
it "…" doで始まるのがテストですね
visit '/static_pages/home'
上の行は、Capybaraのvisit機能を使って、ブラウザでの/static_pages/homeURLへのアクセスをシミュレーションします。
expect(page).to have_content('Sample App')
その次の行 (上のコード) では、これもCapybaraが提供するpage変数を使って、アクセスした結果のページに正しいコンテンツが表示されているかどうかをテストしています。
ちなみにテストが正常に実行されるようにするためにはspec_helper.rbに
RSpec.configure do |config|
これを追加する必要があります
実際にテストを行ってみます
$ bundle exec rspec spec/requests/static_pages_spec.rb
bundle execをrspecのコマンドの前に置くことで、Gemfile内で定義された環境でRSpecが実行されるように、明示的に指示することができるみたいです。
まずこれを実行するとテストが失敗します
Failure / Error expect (page).to have_content('Sample App') ........
... app/views/static_pages/home.html.erb
...
1 example, 1 failure
間省きますがこんな感じででます
一般的にはこれを「赤色 (Red)」
パスするコードを「緑色 (Green)」と言うそうです
テストにパスするHomeページ用コードを書きます
app/views/static_pages/home.html.erb
<h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p>
見出しがSample Appに変更されたため上のコードはパスします
もう一度見てみると
$ bundle exec rspec spec/requests/static_pages_spec.rb
Finished in.......
1 example, 0 failures
.......
とでます
ちなみに同じようなhelpページとaboutページを追加して
<!DOCTYPE html> <html> <head> <title>Ruby on Rails Tutorial Sample App | Home</title> </head> <body> <h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p> </body> </html>
このようなHTML構造で書いてます
これは
・ページのタイトルがどれもほぼ同じ。
・“Ruby on Rails Tutorial Sample App” が3つのタイトルで共通している。
・HTMLの構造全体が各ページで重複している。
このコードはDRYの原則に反しているのでまとめます
まず埋め込みrubyを使ってhome.html.erbビューのタイトルを直していきます
<% provide(:title, 'Home') %> <!DOCTYPE html> <html> <head> <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title> </head>
ERbと呼ばれている、Rubyの埋め込みの例です
※HTMLビューのファイルの拡張子が.html.erbとなっている理由
provide関数で関連づけてyield関数で挿入します
ちなみに<% ... %>書くと単に実行するだけで
<%= ... %>結果がテンプレートに挿入されます
<%= ... %>はphpで言うところのechoですね
同様に他のページでも編集していきます。
ここで各ページをみていくとタイトルをのぞいてだいたいこーなってます
<% provide(:title, 'Foo') %> <!DOCTYPE html> <html> <head> <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title> </head> <body> Contents </body> </html>
同じにつくったので同じ構造になってる思いますww
Railsには、共通の構造をまとめるためのapplication.html.erbという
特別なレイアウトファイルがあるみたいなので使ってみます。
デフォルトタイトルを埋め込みRubyのコードに差し替えます。
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title> <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> </head> <body> <%= yield %> </body> </html>
<%= yield %>は各ページの内容をレイアウトに挿入するためのものです。
/static_pages/homeにアクセスすると、
home.html.erbの内容がHTMLに変換され、<%= yield %>の位置に挿入されるみたいです
下のこれはそれぞれにインクルードするためのものです
<%= stylesheet_link_tag ... %> <%= javascript_include_tag "application", ... %> <%= csrf_meta_tags %>
ではhome.html.erbのHTML構造を抜くとこんな感じになります
<% provide(:title, 'Home') %> <h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p>
まとめるのが難しかったためほとんどコピペのような形になってしまいました>_<
Ruby アップデート mac
Ruby on Railsのチュートリアルを進めていく途中バージョンが原因でエラーが出たりしたので
バージョンアップ方法を書いておきます
現在のバージョン確認
$ruby -v ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-darwin13.1.0]
現在使っているのがデフォルトで入っていた1.9.3
rbenvでruby2.1.1をインストール
$ rbenv install 2.1.1
rbenv versions コマンドで、インストール済み Ruby のバージョンを確認
$rbenv versions system * 1.9.3-p484 (set by /Users/sawanoissei/.rbenv/version) 2.1.1
ちゃんとされてますねー
ただデフォルトが1.9.3になってます
2.1.1をデフォルトに設定
$ rbenv global 2.1.1 rbenv versions system 1.9.3-p484 * 2.1.1 (set by /Users/ユーザー名.rbenv/version)
これでかわりました
いざプロジェクトを作成!
$ rails new static_app --skip-test-unit rbenv: rails: command not found The `rails' command exists in these Ruby versions: 1.9.3-p484
そりゃそーなんだけどぉrailsの向き先が1.9.3なので
ちなみにこれでも調べられる
rbenv which rails
てことでもっかいgemにインストール
gem install rails
そんで
$ rails new static_app --skip-test-unit
はいできたー
codeigniter DB接続テスト
codeigniterを使って家でも環境を作ろうと思いました。
会社でcodeigniterを使っているんだけど初期設定などは自分では行っていないのでちょうどいいかと
とりあえずDBの接続テストをしました。
まずapplication/config/database.phpを接続するDBに書き換えます。
こんな感じで
$db['default']['hostname'] = 'localhost'; $db['default']['username'] = 'root'; $db['default']['password'] = 'XXXX'; $db['default']['database'] = 'sample'; $db['default']['dbdriver'] = 'mysql'; $db['default']['dbprefix'] = ''; $db['default']['pconnect'] = TRUE; $db['default']['db_debug'] = TRUE; $db['default']['cache_on'] = FALSE; $db['default']['cachedir'] = ''; $db['default']['char_set'] = 'utf8'; $db['default']['dbcollat'] = 'utf8_general_ci'; $db['default']['swap_pre'] = ''; $db['default']['autoinit'] = TRUE; $db['default']['stricton'] = FALSE;
ちなみにテスト用にsampleというdatabaseを作っておきました
自動接続の設定を行ったので
application/config/autoload.phpを
$autoload['libraries' ] = array(’database’);
modelにファイルを追加します。
testディレクトリの下に配置しました。
application/models/test/user.php
<?php class Users extends CI_Model { public $table_name_ = 'user'; function __construct() { ※コンストラクタでは必ず親クラスを継承する parent::__construct(); // database.php で定義したDBに接続する $this->load->database(); } function getAllUsers() { $query = $this->db->get($this->table_name_); if($query->num_rows() > 0) { // 結果セットを連想配列として返す return $query->result_array(); } } ?>
初期のままいじっていないので
welcome.phpに
public function database_test() { $this->load->model('test/users'); $users = $this->users->getAllUsers(); $this->load->view('database_test'); } }
print_rしてみたところ
Array ( [0] => Array ( [id] => 1 [name] => issey ) )
はいok
すごい簡単だけど今日はこれくらいしかできなかった(>_<)
技術を学ぶ上で大事な事
今日はcodeigniterの設定をしていてあまり書く事がないので勉強する上での事を書きたいと思います
技術的な事を勉強する上で
周りより始めるのが遅かったのでどーすれば効率的に
中身の濃い時間をすごせるかを考えていて、
効率的な学び方を調べていたので自分なりの考えをまとめておきます。
・ブログやニュースサイトを読む
だいたいこれはみんなやっているけど時間の合間ですかね
技術系だとはてなやqiitaやitproなど後は興味のある人のブログなど
・自分が学んだ事を相手が興味なさそうでもむりやり話して説明するw
以前働いていた職場で技術系の話を共有する場があってそこから人に教えたり繰り返す事によってより吸収する。
・勉強会やカンファレンスに積極的に参加するまたは企画する
当たりはずれあるけどけどだいたい新しく学ぶ事がある。
・オープンソースのソースコードを読んでみる
これは知り合いにおすすめされた。
・複数の言語を勉強する
これは学び方ではないが、パラダイムが違う言語を勉強したほうがいいと思う。
自分はphp→rubyを少しさわってみてるけどwこれはあまりよくないらしい
・自分よりレベルの高い人と仕事や休日の勉強時間をともにする
正直これが一番大事だと思う。モチベーションもあがるし、自分が遅れている事がよくわかるw
・ブログを書く
これもおすすめされたからやってるんですけどかなりの復習になる。
あと人脈がすごい大事ですね^^ いろんな話を聞いてみたい
それもあってivsサマーに申し込んでみました。
たぶん選ばれないと思うけど参加できたら仕事休みます-w
初深夜勤務
Rails Usersリソース 追記
今日はRilsの基本概念Usersリソースにふれました。
リソースっていってもかなりいろいろな理解があるので
ここでいうリソースとはデータモデルとwebインターフェイスが組み合わさったもの。
データモデルとはRDBMSに格納してあるデータと一緒ですね
データモデルをwebで取り扱えるよ的な理解でいいのかな
user用のデータモデルと組み合わさってUsersリソースみたいです
ユーザーをHTTPプロトコル経由で自由に(CURD)作成/読み出し/更新/削除できるオブジェクトとみなすことができるようになります。
前置きはこのへんで
実際作ってみます
Railsに標準装備されているscaffoldジェネレータを使って作成しました。 rails generateスクリプトにscaffoldコマンドを渡すことで生成されるみたいです。
$ rails generate scaffold User name:string email:string
scaffoldコマンドの引数には、リソース名を単数形にしたもの (この場合はUser) を使用します。
オプションのname:stringとemail:stringがRDBMSでいうカラムみたいなものなのかな
あとidパラメータはRailsによって自動的に主キーとしてデータベースに追加されるみたいです。
するとこんな感じで作成されました!
invoke active_record create db/migrate/20140526163117_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml invoke resource_route route resources :users invoke jbuilder_scaffold_controller create app/controllers/users_controller.rb invoke erb create app/views/users create app/views/users/index.html.erb create app/views/users/edit.html.erb create app/views/users/show.html.erb create app/views/users/new.html.erb create app/views/users/_form.html.erb invoke test_unit create test/controllers/users_controller_test.rb invoke helper create app/helpers/users_helper.rb invoke test_unit create test/helpers/users_helper_test.rb invoke jbuilder exist app/views/users create app/views/users/index.json.jbuilder create app/views/users/show.json.jbuilder invoke assets invoke coffee create app/assets/javascripts/users.js.coffee invoke scss create app/assets/stylesheets/users.css.scss invoke scss create app/assets/stylesheets/scaffolds.css.scss
続いてRakeを使用してデータベースをマイグレート (migrate) する必要があるみたいなので
$ bundle exec rake db:migrate == CreateUsers: migrating ================================= -- create_table(:users) -> 0.0017s == CreateUsers: migrated (0.0018s) ========================
ここでbundle execを使っているのはGem fileに対応するrakeが確実に実行されるようです。 ちなみにこのrakeはunixでいうmakeみたいな感じみたいです。
ここで
http://localhost:3000/usersにアクセスすると
これが表示されるみたいなんだけど
僕のはこれw
エラーをみてみるとrails:rootのアクセス先が違う!
以前作った方に向いていたので
一旦プロセスを殺して、新規作成の方に行き再度起動
※補足
ただ、いちいちローカルの rails サーバーを落として新しいサーバーを立ち上げるとかめんどくさいってとき
デフォルトの起動ポートを変更
通常はlocalhost:3000
require 'rails/commands/server' module Rails class Server def default_options super.merge({ :Port => 4000 }) end end end
これをconfig/boot.rbに追記するとlocalhost:4000 で立ち上がります ちなみに今回だけならこれで立ち上がります
rails s --port 4000
補足でした
ここでnewページを表示してユーザーを作成します!
こんな感じ
URLアクションはいろいろあるので参考までに↓ 拾ってきたやつだけど
今日は以上ですw
herokuセットアップ
Rubyといったらherokuって感じがするのでデプロイ先はherokuを使ってみます。
そもそもherokuとは
WEBサーバ・gitリポジトリ・管理機能をまとめた必要最低限の機能を無料で提供してます。
簡単に言うと、プログラムが動作可能なサーバーを無料で使えるってわけです。
有料もあり
あーあとブログのカテゴリーはほんとは分けた方がいんですけど元々herokuはRuby用に開発されたので、 Rubyのカテゴリーに入れちゃいます。
まずGemfileに下を追加
group :production do gem 'pg', '0.15.1' gem 'rails_12factor', '0.0.2' end
herokuはポスグレが使えるので pg gem と
rails_12factorは画像やスタイルシートなどの静的なアセットを提供するためにHerokuで使用されるみたいです。
-without productionオプションを追加してインストールします
$ bundle install --without production
ローカルにはインストールしないという事です
まぁGemfile.lockを更新したいだけですね
でコミット
次にherokuのアカウント登録をしました
ログインしてみました かっこいい笑
アカウント登録がおわりーの
Heroku Toolbeltを使ってherokuソフトをインストールします。
ターミナルでherokuのアカウント設定
$ heroku login
herokuにアプリケーション作成
$ heroku create
このコマンドを実行するとRails専用のサブドメインが作成されてブラウザで確認することができます。
ブラウザで確認。
$ heroku open
Rails 4.0はルートへのルーティングを設定しなければいけません。
ただまだデプロイしていないので
gitでherokuにデプロイします
$ git push heroku master
まとめ herokuにはいっぱいコマンドがあるみたいなのでゆっくりみていきたいと思います。