2008-12-07 Railsで作るTwitterもどき (5)
[Rails] Railsで作るTwitterもどき (ヘルパ、ビュー編)
これまでの流れ:
Railsで作るTwitterもどき (1) モデル編他
Railsで作るTwitterもどき (3) 下準備 2
Railsで作るTwitterもどき (4) コントローラ編
まず、全体的なレイアウトを決めておく。
ヘッダとフッタがあって、中身がある感じ。
app/views/layouts/ にレイアウト用のファイルを作る。
全体のレイアウト。
app/views/layouts/layout.html.erb
<%= render :partial => "layouts/header" %> <%= @content_for_layout %> <%= render :partial => "layouts/footer" %>
ヘッダ
app/views/layouts/_header.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <title>twitterもどき</title> <%= javascript_include_tag :defaults %> <%= stylesheet_link_tag "style" %> <%= @content_for_header %> </head> <body> <div style="text-align: right; margin-right: 2em;"> <% if logged_in? %> <%= link_to 'home', home_path %> | <%= link_to 'ログアウト', logout_path %> <% else %> <%= link_to 'ログイン', login_path %> <% end %> </div>
ヘッダにはログイン、ログアウト用のリンクも用意しておいた。
フッタ
app/views/layouts/_footer.html.erb
<%#= debug(params) %> <%#= debug(session) %> </body> </html>
debug(params) とかはデバッグ用に入れておくと良いかも。コメントアウトしている # を取ると、paramsやsessionの中身が表示されるようになる。
ApplicationControllerで、いま定義したレイアウトを使用するようにする。
# app/controllers/application.rb class ApplicationController < ActionController::Base # 略 layout "layout" # 略 end
次にヘルパを用意する。
大体使いそうなものをリストアップして、それぞれ使いそうな場所を想定して実装。
- ユーザのページへのリンク
- 個別発言へのリンク
- つぶやき削除用リンク
- つぶやきが自分のつぶやきかどうかを調べるヘルパ
この辺を実装してみる。
全体から使いそうなものは application_helperへ。
# app/helpers/application_helper.rb module ApplicationHelper # ユーザへのリンク def link_to_user(user) link_to h(user.login), :controller => :members, :action => :show, :user => user.login end end
つぶやき関連は tweets_hepler へ。
# app/helpers/tweets_helper.rb module TweetsHelper # 個別発言へのリンク def link_to_tweet(tweet) link_to h(tweet.created_at.to_s(:jp)), { :controller => :tweets, :action => :show, :user => tweet.user.login, :id => tweet.id } end # つぶやき削除用リンク def link_to_destroy(tweet) link_to '削除', :controller => :tweets, :action => :destroy, :id => tweet.id if params[:controller] == "members" end # 自分のつぶやきかどうか def my_tweet?(tweet) tweet.user_id == current_user.id end end
個別発言へのリンクは、本家Twitterと同じく発言日時にリンクを張る。
ここでは簡単のため、つぶやき削除は、自分のページからしか行えないことにする。
あとはゴリゴリとviewを書いていくだけ。
自分のホーム。
app/views/members/home.html.erb
<div id="page" class="clearfix"> <div id="content"> <%= render :partial => 'content' %> </div> <div id="sidebar"> <%= render :partial => 'sidebar' %> </div> </div>
partialで分割。
つぶやき用formと、つぶやき一覧。
app/views/members/_content.html.erb
<%- if logged_in? -%> <% form_for :tweet, :url => { :action => :update } do |f| %> いまなにしてる?<br /> <%= f.text_field :body, :style => "padding: 0.5em; font-size: 1.2em;" %> <%= f.submit "投稿する" %> <% end %> <%- end -%> <div id="tweets"> <%= render :partial => '/members/tweets' %> </div>
つぶやき欄はちょっと大きくしておいた。
つぶやき一覧。
will_paginateでページ送り。
app/views/members/_tweets.html.erb
<%- @tweets.each do |t| -%> <%= link_to_user(t.user) %> : <%= h t.body %> <span class="timestamp">(<%= link_to_tweet(t) %>)</span> <%- if logged_in? -%> <%= link_to_destroy(t) if my_tweet?(t) %> <%- end -%> <br /> <%- end -%> <p> <%= will_paginate @tweets, :previous_label => "« 前へ", :next_label => "» 次へ" %> </p>
サイドバーにはユーザ名他の情報を。
このサイドバーは自分のホームと、その他のユーザのページで使い回すので、条件分岐で表示するものを若干変えてある。
app/views/members/_sidebar.html.erb
<%- if logged_in? && me? -%> <h1><%= h @user.login %></h1> <p> あなたがフォロー: <%= link_to h(@user.friends.size), friends_path %><br /> あなたをフォロー: <%= link_to h(@user.followers.size), followers_path %><br /> これまでの投稿: <%= link_to h(@user.tweets.size), :controller => :members, :action => :show, :user => @user.login %> </p> <%- else -%> <p> あなたがフォロー: <%= link_to h(@user.friends.size), :controller => :members, :action => :friends, :user => @user.login %><br /> あなたをフォロー: <%= link_to h(@user.followers.size), :controller => :members, :action => :followers, :user => @user.login %><br /> これまでの投稿: <%= link_to h(@user.tweets.size), :controller => :members, :action => :show, :user => @user.login %> </p> <%- end -%> <p> <%= link_to '公開つぶやき', :controller => :tweets, :action => :list %> </p> <div id="friends"> フォロー中 <br /> <%- @user.friends.each do |u| -%> <%= link_to_user(u) %> <%- end -%> </div>
他ユーザのページ。
app/views/members/show.html.erb
<div id="page" class="clearfix"> <div id="content"> <h1><%= h @user.login %></h1> <%- if logged_in? && !me? -%> <p> <%= link_to_remote friend? ? "フォロー解除" : "フォローする", { :url => { :controller => :members, :action => :ajax_toggle_follow, :id => @user.id } }, :id => "follow" %> </p> <%- end -%> <div id="tweets"> <%= render :partial => '/members/tweets' %> </div> </div> <div id="sidebar"> <%= render :partial => 'sidebar' %> </div> </div>
ログインしていて、自分自身では無いときだけ、フォロー、フォロー解除のリンクを表示。
フォロー、フォロー解除は、このページからだけ行えることにした。Ajaxなので link_to_remote。
ここで使っている friend? というヘルパは、自分がフォローしているユーザかどうかを返すもの。以下のようにApplicationControllerに追加しておいた。
関連テーブルを調べて、自分がフォローしているユーザかどうかを返す。
# app/controllers/application.rb class ApplicationController < ActionController::Base # 略 helper_method :me?, :friend? # 略 protected def friend? !me? && !!Friendship.find_by_user_id_and_friend_id(@current_user.id, @user.id) end
自分がフォローしているユーザの一覧。
app/views/members/friends.html.rb
<div id="page" class="clearfix"> <div id="content"> <h1><%= h @user.login %> がフォロー</h1> <%- @friends.each do |u| -%> <%= link_to_user u %><br /> <%- end -%> <p> <%= will_paginate @friends, :previous_label => "« 前へ", :next_label => "» 次へ" %> </p> </div> </div>
自分のフォロワー一覧。
app/views/members/followers.html.erb
<div id="page" class="clearfix"> <div id="content"> <h1><%= h @user.login %> をフォロー</h1> <%- @followers.each do |u| -%> <%= link_to_user u %> <br /> <%- end -%> <p> <%= will_paginate @followers, :previous_label => "« 前へ", :next_label => "» 次へ" %> </p> </div> </div>
個別発言(1つのつぶやきへのパーマリンク)。
app/views/tweets/show.html.erb
<div id="page"> <h1><%= link_to_user(@tweet.user) %></h1> <span style="font-size: larger;"><%= h @tweet.body %></span> <br /> (<%= h @tweet.created_at.to_s(:jp) %>) </div>
公開つぶやき一覧。
app/views/tweets/list.html.erb
<div id="page" class="clearfix"> <div id="content"> <%= render :partial => '/members/tweets' %> </div> </div>
最後に、適当な二段組みのスタイルシートを用意してみる。
public/stylesheets/style.css
.clearfix:after { content: "."; display: block; clear: both; height: 0px; visibility: hidden; } #page { width: 900px; margin: 0; margin-left: auto; margin-right: auto; padding: 0; } #sidebar { float: right; width: 200px; height: auto; } #content { float: left; width: 650px; height: 600px; padding: 1em; border-right: solid 1px #ccc; } .timestamp { color: #aaa; } .timestamp a { color: #aaa; text-decoration: none; } .timestamp a:hover { color: #00f; text-decoration: underline; }
なんだか駆け足になってしまったが、これで一通りはできあがりだ。
大西 2010/02/11 06:14 このRailsで作るTwitterもどきを有料でわけていただけますか?当方のサイトで運営したく思います。どうかよろしくお願いします。
hichiriki 2010/02/11 12:27 このページの通りに作ってしまえば、誰でも無料でできますよ。
ただし、このTwitterもどきはRailsのチュートリアルとして説明用に作ったものですので、リプライ機能などTwitterには存在する基本的な機能も備えていません。またアクセスが集中した場合のスケールアウトなどに関しても、考慮されていません。
その辺りはご了承ください。
hichiriki 2010/02/11 13:05 コメントにメール欄(非公開)がありますので、どうしてもという場合は連絡先メールアドレスを記入してください。
よろしくお願いします。
大西 2010/02/11 16:20 ありがとうございます。メールアドレスを記入しました。厚かましいお願いですが、できれば当方のサーバーに設置して戴ければ幸甚です。
今後の開発も含めてご相談にのって戴ければ幸甚です。いいドメインを取得致しましたもので、、、