Ruby on Rails チュートリアル 実例を使ってRailsを学ぼう 第5章を見ながらやったことを、あとでもう一度できるようにまとめます!!第五章!!
- Bootstrap
- パーシャル
- Railsのルーティング
- Asset Pipeline
- Sass
- RSpecリファクタリング
準備
$ git checkout -b filling-in-layout
ナビゲーションをつける
レイアウトファイルを修正
$ subl app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav pull-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</div>
</div>
</header>
<div class="container">
<%= yield %>
</div>
</body>
</html>
Homeページを修正
<div class="center hero-unit">
<h1>Welcome to the Sample App</h1>
<h2>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</h2>
<%= link_to "Sign up now!", '#', class: "btn btn-large btn-primary" %>
</div>
<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %>
画像をダウンロード
$ cd app/assets/images/
$ wget http://rubyonrails.org/images/rails.png
$ cd ../../..
bootstrapとカスタムCSS
Gemfileにbootstrap-sassを追加する。
$ subl Gemfile
gem 'rails', '4.0.0'
+gem 'bootstrap-sass', '2.3.2.0'
group :development, :test do
gem 'sqlite3', '1.3.7'
bundle インストール
$ bundle install
Asset Pipelineと互換性を持つ為の設定をする。
$ subl config/application.rb
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*. {rb,yml}').to_s]
# config.i18n.default_locale = :de
+
+ config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
end
end
カスタムCSSを追加する為のファイルを作成する
$ touch app/assets/stylesheets/custom.css.scss
$ subl app/assets/stylesheets/custom.css.scss
+ @import "bootstrap";
さらにカスタムCSSを修正
$ subl app/assets/stylesheets/custom.css.scss
@import "bootstrap";
/* universal */
html {
overflow-y: scroll;
}
body {
padding-top: 60px;
}
section {
overflow: auto;
}
textarea {
resize: vertical;
}
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
/* typography */
h1, h2, h3, h4, h5, h6 {
line-height: 1;
}
h1 {
font-size: 3em;
letter-spacing: -2px;
margin-bottom: 30px;
text-align: center;
}
h2 {
font-size: 1.2em;
letter-spacing: -1px;
margin-bottom: 30px;
text-align: center;
font-weight: normal;
color: #999;
}
p {
font-size: 1.1em;
line-height: 1.7em;
}
/* header */
#logo {
float: left;
margin-right: 10px;
font-size: 1.7em;
color: #fff;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
line-height: 1;
}
#logo:hover {
color: #fff;
text-decoration: none;
}
パーシャル (partial)
レイアウトファイルの内容を別ファイルに分ける。
$ subl app/views/layouts/_shim.html.erb
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
ヘッダーをパーシャルで定義。
$ subl app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav pull-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</div>
</div>
</header>
フッターも。
$ subl app/views/layouts/_footer.html.erb
<footer class="footer">
<small>
<a href="http://railstutorial.jp/">Rails Tutorial</a>
by Michael Hartl
</small>
<nav>
<ul>
<li><%= link_to "About", '#' %></li>
<li><%= link_to "Contact", '#' %></li>
<li><a href="http://news.railstutorial.jp/">News</a></li>
</ul>
</nav>
</footer>
レイアウトファイルにパーシャルを適用
$ subl app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
</div>
</body>
</html>
フッターの見た目を良くする。CSS修正。
$subl app/assets/stylesheets/custom.css.scss
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #999;
}
footer a {
color: #555;
}
footer a:hover {
color: #222;
}
footer small {
float: left;
}
footer ul {
float: right;
list-style: none;
}
footer ul li {
float: left;
margin-left: 10px;
}
SassとAsset Pipeline
アセットディレクトリ
- app/assets: 現在のアプリケーション固有のアセット
- lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
- vendor/assets: サードパーティのアセット
マニフェストファイル
アセットファイルをどのように一つにするのかをRailsに伝える。
app/assets/stylesheets/application.css
プリプロセッサエンジン
coffeeスクリプト, scss, erbをコンパイルするプロセッサ。
SCSS
ネスト
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
↑これを↓こうかける。
.center {
text-align: center;
h1 {
margin-bottom: 10px;
}
}
変数
h2 {
.
.
.
color: #999;
}
.
.
.
footer {
.
.
.
color: #999;
}
↑これを↓こうかける。
$lightGray: #999;
.
.
.
h2 {
.
.
.
color: $lightGray;
}
.
.
.
footer {
.
.
.
color: $lightGray;
}
scssを使って書き換えたカスタムCSS
$ subl app/assets/stylesheets/custom.css.scss
@import "bootstrap";
/* mixins, variables, etc. */
$grayMediumLight: #eaeaea;
/* universal */
html {
overflow-y: scroll;
}
body {
padding-top: 60px;
}
section {
overflow: auto;
}
textarea {
resize: vertical;
}
.center {
text-align: center;
h1 {
margin-bottom: 10px;
}
}
/* typography */
h1, h2, h3, h4, h5, h6 {
line-height: 1;
}
h1 {
font-size: 3em;
letter-spacing: -2px;
margin-bottom: 30px;
text-align: center;
}
h2 {
font-size: 1.2em;
letter-spacing: -1px;
margin-bottom: 30px;
text-align: center;
font-weight: normal;
color: $grayLight;
}
p {
font-size: 1.1em;
line-height: 1.7em;
}
/* header */
#logo {
float: left;
margin-right: 10px;
font-size: 1.7em;
color: white;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
line-height: 1;
&:hover {
color: white;
text-decoration: none;
}
}
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid $grayMediumLight;
color: $grayLight;
a {
color: $gray;
&:hover {
color: $grayDarker;
}
}
small {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 10px;
}
}
}
Railsのルート
テストを名前付きルートを使ったものに修正する。
$ spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the h1 'Sample App'" do
visit root_path
expect(page).to have_content('Sample App')
end
it "should have the base title" do
visit root_path
expect(page).to have_title("Ruby on Rails Tutorial Sample App")
end
it "should not have a custom page title" do
visit root_path
expect(page).not_to have_title('| Home')
end
end
describe "Help page" do
it "should have the h1 'Help'" do
visit help_path
expect(page).to have_content('Help')
end
it "should have the title 'Help'" do
visit help_path
expect(page).to have_title("Ruby on Rails Tutorial Sample App | Help")
end
end
describe "About page" do
it "should have the h1 'About Us'" do
visit about_path
expect(page).to have_content('About Us')
end
it "should have the title 'About Us'" do
visit about_path
expect(page).to have_title("Ruby on Rails Tutorial Sample App | About Us")
end
end
describe "Contact page" do
it "should have the content 'Help'" do
visit contact_path
expect(page).to have_content('Contact')
end
it "should have the title 'Contact'" do
visit contact_path
expect(page).to have_title("Ruby on Rails Tutorial Sample App | Contact")
end
end
end
テストする
$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 名前付きルートが定義されてないから失敗する。
ルートの定義を修正する。
$ subl config/routes.rb
SampleApp::Application.routes.draw do
- get "static_pages/home"
- get "static_pages/help"
- get "static_pages/about"
- get "static_pages/contact"
+ root 'static_pages#home'
+ match '/help', to: 'static_pages#help', via: 'get'
+ match '/about', to: 'static_pages#about', via: 'get'
+ match '/contact', to: 'static_pages#contact', via: 'get'
+ match '/about', to: 'static_pages#about', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
↑このコードは、↓この名前付きルートを生成する
about_path -> '/about'
about_url -> 'http://localhost:3000/about'
レイアウトファイルのリンクを修正
ヘッダ
$ subl app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<%= link_to "sample app", root_path, id: "logo" %>
<nav>
<ul class="nav pull-right">
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</div>
</div>
</header>
フッタ
$ subl touch app/views/layouts/_footer.html.erb
<footer class="footer">
<small>
<a href="http://railstutorial.jp/">Rails Tutorial</a>
by Michael Hartl
</small>
<nav>
<ul>
<li><%= link_to "About", about_path %></li>
<li><%= link_to "Contact", contact_path %></li>
<li><a href="http://news.railstutorial.jp/">News</a></li>
</ul>
</nav>
</footer>
RSpecを洗練させる
RSpecユーティリティ用ファイルを作成
$ subl spec/support/utilities.rb
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
RSpecをもっとシンプルに書く
$ subl spec/support/utilities.rb
require 'spec_helper'
describe "Static pages" do
subject { page }
describe "Home page" do
before {visit root_path}
it {should have_content('Sample App')}
it {should have_title(full_title(''))}
it {should_not have_title('| Home')}
end
describe "Help page" do
before {visit help_path}
it {should have_content('Help')}
it {should have_title(full_title('Help'))}
end
describe "About page" do
before {visit about_path}
it {should have_content('About Us')}
it {should have_title(full_title('About Us'))}
end
describe "Contact page" do
before {visit contact_path}
it {should have_content('Contact')}
it {should have_title(full_title('Contact'))}
end
end
Usersコントローラ作成
コントローラファイルを生成
$ rails generate controller Users new --no-test-framework
テスト作成
$ rails generate integration_test user_pages
$ subl spec/requests/user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign up') }
it { should have_title(full_title('Sign up')) }
end
end
テスト実行
$ bundle exec rspec spec/requests/user_pages_spec.rb
=> 失敗する
$ bundle exec rspec spec/ #と実行すると全てのテストを実行する。
テストをパスするように修正
ルートを修正
SampleApp::Application.routes.draw do
get "users/new"
root 'static_pages#home'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
+ match '/signup', to: 'users#new', via: 'get'
ビューを修正
+ <% provide(:title, 'Sign up') %>
+ <h1>Sign up</h1>
<p>Find me in app/views/users/new.html.erb</p>
テスト実行
$ bundle exec rspec spec/requests/user_pages_spec.rb
=> 成功する
HomeページのSignupボタンにリンクを設定
<div class="center hero-unit">
<h1>Welcome to the Sample App</h1>
<h2>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</h2>
<%= link_to "Sign up now!", signup_path, class: "btn btn-large btn-primary" %>
</div>
<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %>
gitにコミット
$ git add .
$ git commit -m "Finish layout and routes"
$ git checkout master
$ git merge filling-in-layout