Goal
テンプレートをリファクタリングする。
Dev-Environment
OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4
Wait a minute
遅れました~すいません。
リファクタリング第三弾!
リファクタリング第三弾!
ここでやること・・・
- カスタムCSSの導入
- 記述/名称の修正
- テンプレート分割
- 冗長な部分の共通化
Index
Templates refactoring
|> The introduction of custom CSS
|> Improvement of template
|> Modify the view
|> The introduction of custom CSS
|> Improvement of template
|> Modify the view
The introduction of custom CSS
カスタムCSSを導入します。
遅すぎる導入ですが、ここまで来ると修正も面倒な状態に・・・
遅すぎる導入ですが、ここまで来ると修正も面倒な状態に・・・
Rails Tutorial(Github)のcustom.css.scssを使いたかったのですが、
Phoenix-Frameworkでscssを利用できなかったため、一度CSSに変換して利用しています。
多分、Phoenix-Frameworkだとscss(sass?)に対応してないのでしょう。
Phoenix-Frameworkでscssを利用できなかったため、一度CSSに変換して利用しています。
多分、Phoenix-Frameworkだとscss(sass?)に対応してないのでしょう。
ファイル: priv/static/css/custom.css (新規)
@import url("app.css");
/* 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: #777777;
}
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;
}
#logo:hover {
color: white;
text-decoration: none;
}
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #777777;
}
footer a {
color: #555555;
}
footer a:hover {
color: #222222;
}
footer small {
float: left;
}
footer ul {
float: right;
list-style: none;
}
footer ul li {
float: left;
margin-left: 10px;
}
/* miscellaneous */
.debug_dump {
clear: both;
float: left;
width: 100%;
margin-top: 45px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/* sidebar */
aside section {
padding: 10px 0;
border-top: 1px solid #eeeeee;
}
aside section:first-child {
border: 0;
padding-top: 0;
}
aside section span {
display: block;
margin-bottom: 3px;
line-height: 1;
}
aside section h1 {
font-size: 1.4em;
text-align: left;
letter-spacing: -1px;
margin-bottom: 3px;
margin-top: 0px;
}
.gravatar {
float: left;
margin-right: 10px;
}
.stats {
overflow: auto;
}
.stats a {
float: left;
padding: 0 10px;
border-left: 1px solid #eeeeee;
color: gray;
}
.stats a:first-child {
padding-left: 0;
border: 0;
}
.stats a:hover {
text-decoration: none;
color: #3677a3;
}
.stats strong {
display: block;
}
.user_avatars {
overflow: auto;
margin-top: 10px;
}
.user_avatars .gravatar {
margin: 1px 1px;
}
/* forms */
input, textarea, select, .uneditable-input {
border: 1px solid #bbb;
width: 100%;
margin-bottom: 15px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
input {
height: auto !important;
}
#error_explanation {
color: #f00;
}
#error_explanation ul {
list-style: none;
margin: 0 0 18px 0;
}
/* Users index */
.users {
list-style: none;
margin: 0;
}
.users li {
overflow: auto;
padding: 10px 0;
border-top: 1px solid #eeeeee;
}
.users li:last-child {
border-bottom: 1px solid #eeeeee;
}
/* microposts */
.microposts {
list-style: none;
margin: 10px 0 0 0;
}
.microposts li {
padding: 10px 0;
border-top: 1px solid #e8e8e8;
}
.content {
display: block;
}
.timestamp {
color: #777777;
}
.gravatar {
float: left;
margin-right: 10px;
}
aside textarea {
height: 100px;
margin-bottom: 5px;
}
ファイル: web/templates/layout/applicaiton.html.eex (追加)
CSSの読み込みを追加。
<link rel="stylesheet" href="<%= static_path(@conn, "/css/custom.css") %>">
Improvement of template
テンプレートの改善をしていきます。
Caution:
修正した分量多いので、修正前の状態は記述しません。
修正した分量多いので、修正前の状態は記述しません。
ファイル: web/templates/user/input_form.html.eex (変更)
名称を変更しました。
変更後: web/templates/user/user_form.html.eex
ファイル: web/templates/user/new.html.eex (変更)
input_form.html.eexの名称変更に伴う変更。
<h1>Sign up</h1>
<%= render "user_form.html", changeset: @changeset,
action: user_path(@conn, :create) %>
ファイル: web/templates/user/edit.html.eex (変更)
input_form.html.eexの名称変更に伴う変更。
<h2>Edit UserProfile</h2>
<%= render "user_form.html", changeset: @changeset,
action: user_path(@conn, :update, @user) %>
ファイル: web/templates/user/index.html.eex (修正)
テンプレートを改善。(分割と共通化)
<h1>All users</h1>
<%= if !is_empty_list?(@users) do %>
<%= render SampleApp.PaginationView, "pagination.html",
action: user_path(@conn, :index),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<ul class="users">
<%= for user <- @users do %>
<%= render "user.html", conn: @conn, user: user %>
<% end %>
</ul>
<%= render SampleApp.PaginationView, "pagination.html",
action: user_path(@conn, :index),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
ファイル: web/templates/user/show.html.eex (修正)
テンプレートを改善。(分割と共通化)
<h2>User profile</h2>
<div class="row">
<aside class="span4">
<section>
<%= render SampleApp.SharedView, "user_info.html", conn: @conn, user: @user %>
</section>
<section>
<%= render SampleApp.SharedView, "stats.html", conn: @conn, user: @user %>
</section>
<%= if current_user?(@conn, @user) do %>
<section>
<%= link "Edit", to: user_path(@conn, :edit, @user), class: "btn btn-default btn-xs" %>
<%= link "Delete", to: user_path(@conn, :delete, @user), method: :delete, class: "btn btn-danger btn-xs" %>
</section>
<% end %>
<section>
<%= render "micropost_form.html", conn: @conn, changeset: @changeset, user: @user %>
</section>
</aside>
<div class="span8">
<%= render "follow_form.html", conn: @conn, user: @user %>
<h3>Microposts</h3>
<%= unless is_empty_list?(@posts) do %>
<%= render SampleApp.SharedView, "microposts.html", conn: @conn, posts: @posts, user: @user %>
<%= render SampleApp.PaginationView, "pagination.html",
action: user_path(@conn, :show, @user),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
</div>
</div>
ファイル: web/templates/user/show_follow.html.eex (修正)
テンプレートを改善。(分割と共通化)
<div class="row">
<aside class="span4">
<section>
<%= render SampleApp.SharedView, "user_info.html", conn: @conn, user: @user %>
</section>
<section>
<%= render SampleApp.SharedView, "stats.html", conn: @conn, user: @user %>
<%= if @users do %>
<div class="user_avatars">
<%= for follow_user <- @users do %>
<a href="<%= user_path(@conn, :show, follow_user) %>">
<img src="<%= get_gravatar_url(follow_user) %>" class="gravatar">
</a>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="span8">
<h3>Users</h3>
<%= if @users do %>
<ul class="users">
<%= for follow_user <- @users do %>
<%= render "user.html", conn: @conn, user: follow_user %>
<% end %>
</ul>
<%= render SampleApp.PaginationView, "pagination.html",
action: @action,
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
</div>
</div>
ファイル: web/templates/user/user.html.eex (新規)
<li>
<img src="<%= get_gravatar_url(@user) %>" class="gravatar">
<%= link @user.name, to: user_path(@conn, :show, @user) %>
</li>
ファイル: web/templates/user/micropost_form.html (新規)
<%= if current_user?(@conn, @user) do %>
<%= form_for @changeset, micropost_path(@conn, :create), fn f -> %>
<%= hidden_input f, :user_id %>
<%= if f.errors != [] do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below:</p>
<ul>
<%= for {attr, message} <- f.errors do %>
<li><%= humanize(attr) %> <%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<label>Content</label>
<%= textarea f, :content, class: "form-control" %>
<%= submit "Post", class: "btn btn-primary" %>
</div>
<% end %>
<% end %>
ファイル: web/templates/user/follow_form.html (新規)
<%= unless current_user?(@conn, @user) do %>
<div id="follow_form">
<%= if following?(@conn, @user.id) do %>
<%= form_tag(relationship_path(@conn, :delete, current_user(@conn)), method: :delete) %>
<input type="hidden" name="unfollow_id" value="<%= @user.id %>">
<%= submit "Unfollow", class: "btn btn-large" %>
</form>
<% else %>
<%= form_tag(relationship_path(@conn, :create), method: :post) %>
<input type="hidden" name="id" value="<%= current_user(@conn).id %>">
<input type="hidden" name="follow_id" value="<%= @user.id %>">
<%= submit "Follow", class: "btn btn-large btn-primary" %>
</form>
<% end %>
</div>
<% end %>
ディレクトリ: web/templates/shared/ (新規)
ディレクトリを作成。
ファイル: web/templates/shared/microposts.html.eex (新規)
<ol class="microposts">
<li>
<%= for post <- @posts do %>
<span class="content"><%= post.content %></span>
<span class="timestamp">
Posted <%= post.inserted_at %> ago.
</span>
<%= link "Delete", to: micropost_path(@conn, :delete, post), method: :delete, class: "btn btn-danger btn-xs" %>
<% end %>
</li>
</ol>
ファイル: web/templates/shared/stats.html.eex (新規)
<div class="stats">
<a href="<%= user_path(@conn, :following, @user) %>">
<strong id="following" class="stat">
(<%= Enum.count(@user.followed_users) %>)
</strong>
following
</a>
<a href="<%= user_path(@conn, :followers, @user) %>">
<strong id="followers" class="stat">
(<%= Enum.count(@user.followers) %>)
</strong>
followers
</a>
</div>
ファイル: web/templates/shared/user_info_html.eex (新規)
<a href="<%= user_path(@conn, :show, @user) %>">
<img src="<%= get_gravatar_url(@user) %>" class="gravatar">
</a>
<h1><%= @user.name %></h1>
<span>
<%= link "view profile", to: user_path(@conn, :show, @user), class: "btn btn-default btn-xs" %>
</span>
Modify the view
ビューの変更を行います。
ファイル: web/views/shared_view.ex (新規)
defmodule SampleApp.SharedView do
use SampleApp.Web, :view
end
ファイル: web/views/user_view.ex (関数削除)
defmodule SampleApp.UserView do
use SampleApp.Web, :view
def is_empty_list?(list) when is_list(list) do
list == []
end
def following?(conn, follow_user_id) do
SampleApp.Relationship.following?(conn.assigns[:current_user].id, follow_user_id)
end
end
ファイル: lib/helpers/view_helper.ex (関数追加)
defmodule SampleApp.Helpers.ViewHelper do
def current_user(conn) do
conn.assigns[:current_user]
end
def current_user?(conn, %SampleApp.User{id: id}) do
user = SampleApp.Repo.get(SampleApp.User, id)
conn.assigns[:current_user] == user
end
def get_gravatar_url(%SampleApp.User{email: email}) do
SampleApp.Gravator.get_gravatar_url(email, 50)
end
end
Speaking to oneself
テンプレートのリファクタリングは完了。
Rails Tutorialでやっているテンプレート構成に修正しました。
Rails Tutorialでやっているテンプレート構成に修正しました。
最初からやれよ!?って話ですが、
CSSの適応ができなかったので、仕方なく自分で作っていました。
(その結果が散々なあれですが・・・)
CSSの適応ができなかったので、仕方なく自分で作っていました。
(その結果が散々なあれですが・・・)
CSSの適応方法が分かったので、今回Rails Tutorialの方へ合わせました。
(まだ、足りないところはありますが・・・)
(まだ、足りないところはありますが・・・)
後は、CSSの修正ですね・・・デザインがRails Tutorialのように表示されません。
こいつも追々やっていきます。
こいつも追々やっていきます。
今回の差分はこちら・・・
Github: darui00kara/phoenix_tutorial - Templates refactoring
Github: darui00kara/phoenix_tutorial - Templates refactoring
ってかこれ、リファクタリングってより・・・改修っぽい?