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
リファクタリング第二弾。
今度は、ビューに関連する部分をリファクタリングしていきます。
Index
View refactoring
|> To use in common the function (LayoutView.current_user/1)
|> Modification of function (UserView.current_user/2)
|> Create gravator module
|> Create pagination view module
|> To use in common the function (LayoutView.current_user/1)
|> Modification of function (UserView.current_user/2)
|> Create gravator module
|> Create pagination view module
To use in common the function. (LayoutView.current_user/1)
LayoutView.current_user/1をuser_viewでも使いたい場面がありました。
その時は、show.html.eexにてconnから直接、現在のユーザを取得していましたね。
その時は、show.html.eexにてconnから直接、現在のユーザを取得していましたね。
LayoutViewに関数があるのに使わないのは勿体ないです。
しかし、別のビューから関数を呼ぶのは分かり辛くなります。
しかし、別のビューから関数を呼ぶのは分かり辛くなります。
なので、対象の関数を共通で使えるようします。
ファイル: lib/helpers/view_helper.ex
新しくビューを補助するモジュールを作成。
defmodule SampleApp.Helpers.ViewHelper do
def current_user(conn) do
conn.assigns[:current_user]
end
end
ファイル: web/web.ex
それぞれのモジュールでインポートしてもいいのですが、
web.exで全ビューに対して一括でインポートさせます。
web.exで全ビューに対して一括でインポートさせます。
def view do
quote do
...
# My view helper
import SampleApp.Helpers.ViewHelper
end
end
ファイル: web/views/layout_view.ex
以下の関数をLayoutViewから削除して下さい。
- current_user/1
ファイル: web/templates/user/show.html.eex
修正前:
<%= if !current_user?(@conn, @user) do %>
<%= if !following?(@conn, @user.id) do %>
<%= form_tag(relationship_path(@conn, :create), method: :post) %>
<input type="hidden" name="id" value="<%= @conn.assigns[:current_user].id %>">
<input type="hidden" name="follow_id" value="<%= @user.id %>">
<%= submit "Follow", class: "btn btn-primary" %>
</form>
<% else %>
<%= form_tag(relationship_path(@conn, :delete, @conn.assigns[:current_user]), method: :delete) %>
<input type="hidden" name="unfollow_id" value="<%= @user.id %>">
<%= submit "Unfollow", class: "btn btn-primary" %>
</form>
<% end %>
<% end %>
修正後:
<%= if !current_user?(@conn, @user) do %>
<%= if !following?(@conn, @user.id) do %>
<%= 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-primary" %>
</form>
<% else %>
<%= 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-primary" %>
</form>
<% end %>
<% end %>
Modification of function (UserView.current_user/2)
UserView.current_user/2の処理と場所を変更します。
ファイル: lib/helpers/view_helper.ex
以下の関数を追加して下さい。
def current_user?(conn, %SampleApp.User{id: id}) do
user = SampleApp.Repo.get(SampleApp.User, id)
conn.assigns[:current_user] == user
end
ファイル: web/views/user_view.ex
以下の関数をUserViewから削除して下さい。
- current_user?/2
Create gravator module
Gravator用のモジュールを作成します。
ファイル: lib/gravator.ex
defmodule SampleApp.Gravator do
def get_gravatar_url(email, size) do
gravatar_id = email_to_gravator_id(email)
"https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
end
defp email_to_gravator_id(email) do
email |> email_downcase |> email_crypt_md5
end
defp email_crypt_md5(email) do
:erlang.md5(email)
|> :erlang.bitstring_to_list
|> Enum.map(&(:io_lib.format("~2.16.0b", [&1])))
|> List.flatten
|> :erlang.list_to_bitstring
end
defp email_downcase(email) do
String.downcase(email)
end
end
ファイル: web/views/user_view.ex
以下の関数をUserViewから削除して下さい。
- email_crypt_md5/1
- email_downcase/1
また、以下のように関数の修正をして下さい。
修正前:
def get_gravatar_url(%User{email: email}) do
gravatar_id = email |> email_downcase |> email_crypt_md5
"https://secure.gravatar.com/avatar/#{gravatar_id}?s=50"
end
修正後:
def get_gravatar_url(%User{email: email}) do
SampleApp.Gravator.get_gravatar_url(email, 50)
end
Create pagination view module
ページネーション用のビューモジュールを作成します。
ファイル: web/views/pagination_view.ex
defmodule SampleApp.PaginationView do
use SampleApp.Web, :view
def get_previous_page_url(action, current_page) do
get_page_url(action, current_page - 1)
end
def get_next_page_url(action, current_page) do
get_page_url(action, current_page + 1)
end
def get_page_url(action, page_number) do
"#{action}?select_page=#{page_number}"
end
end
ファイル: web/templates/user/pagination.html.eex
pagination.html.eexファイルを以下のように移動します。
変更前: web/templates/user/pagination.html.eex
変更後: web/templates/pagination/pagination.html.eex
変更後: web/templates/pagination/pagination.html.eex
ファイル: web/views/user_view.ex
以下の関数をUserViewから削除して下さい。
- get_previous_page_url/2
- get_next_page_url/2
- get_page_url/2
ページネーションの呼び出し部分を変更します。
ファイル: web/templates/user/index.html.eex
変更前:
<%= if !is_empty_list?(@users) do %>
<%= render "pagination.html",
action: user_path(@conn, :index),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
...
<%= render "pagination.html",
action: user_path(@conn, :index),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
変更後:
<%= 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 %>
...
<%= 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
変更前:
<div style="clear: right; margin-left: 250px;">
<h2>Microposts</h2>
...
<%= render "pagination.html",
action: user_path(@conn, :show, @user),
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
</div>
変更後:
<div style="clear: right; margin-left: 250px;">
<h2>Microposts</h2>
...
<%= 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>
ファイル: web/templates/user/show_follow.html.eex
変更前:
<div style="clear: right; margin-left: 250px;">
<%= if @users do %>
...
<%= render "pagination.html",
action: @action,
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
</div>
変更後:
<div style="clear: right; margin-left: 250px;">
<%= if @users do %>
...
<%= render SampleApp.PaginationView, "pagination.html",
action: @action,
current_page: @current_page,
page_list: @page_list,
total_pages: @total_pages %>
<% end %>
</div>
Speaking to oneself
これでUserViewは大分すっきりしたかな?
次はちょっと面倒ですけど、
テンプレートの共通している部分を細かく分割していこうか・・・
テンプレートの共通している部分を細かく分割していこうか・・・
変更点の一覧については以下のリンク先にあります。
変更点: Github - darui00kara/phoenix_tutorial (View refactoring)
変更点: Github - darui00kara/phoenix_tutorial (View refactoring)
Bibliography
特になし