2009年7月27日月曜日

[Rails][習作] 簡易ブックマークアプリ (3)

今回は、ブックマークを作成月で絞り込む機能を追加します。
(あったら結構便利じゃないかと思うのだけれど、私だけかな。)

indexアクション内で、Bookmark.created_atをもとに作成年月のハッシュを作ります。


# app/controllers/bookmarks_controller.rb
def index
# created_at降順でリストを取得
@bookmarks = Bookmark.find(:all, :order=>"created_at desc")

# 作成年-月のハッシュ
@created = Hash.new
@bookmarks.each{ |bookmark|
year = bookmark.created_at.year
month = bookmark.created_at.month
if !@created.key? year
@created.store year, [month]
elsif !@created[year].include? month
@created[year] << month
end
}

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @bookmarks }
end
end


ビュー側は、渡されたハッシュをもとに作成年月のリストを作成するerbコードを追加。

# app/views/bookmarks/index.html.erb
<h1>Listing bookmarks</h1>

<div style="position: absolute; width=700px;">

<div style="position: relative; float: left;">
<table border="1">
<tr>
<th>Url</th>
<th>Tags</th>
<th>Date</th>
</tr>

<% @bookmarks.each do |bookmark| %>
<tr>
<td>
<%=link_to bookmark.url, bookmark.url %><br/>
* <%=h bookmark.comment.force_encoding 'UTF-8' %> <!-- ascii-8bit -> UTF-8 -->
</td>
<td>
<% bookmark.tags.each do |tag| %>
[<%= tag.tag %>]
<% end %>
</td>
<td><%= bookmark.created_at.strftime "%Y/%m/%d" %></td>
<!--td><%#= link_to 'Show', bookmark %></td-->
<td><%= link_to 'Edit', edit_bookmark_path(bookmark) %></td>
<td><%= link_to 'Destroy', bookmark, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>

<br />

<%= link_to 'New bookmark', new_bookmark_path %>
</div>

<div style="position: relative; float: left; margin-left: 10px">
<ul>
<% @created.each do |year, months| %>
<li>
<%= year %>年
<ul>
<% months.each do |month| %>
<li><%= month %>月</li>
<% end %>
</ul>
</li>
<% end %>
</ul>
</div>

</div>


表組みも少しだけ変更。

また、ActiveRecord の String型属性が ascii-8bit で返ってくるため、bookmark.comment に force_encoding('UTF-8')をかけています(ページのcharsetはUTF-8のため、そのままでは "incompatible character encodings: ASCII-8BIT and UTF-8" というエラーが発生)。

Ruby1.9 + sqlite3-ruby で発生する現象とのことです。
参考:Rubyのsqlite3-rubyは必ず文字コードASCII-8BITとして返す

そのうち sqlite3-ruby が修正されて、こんなやっつけは必要なくなる(と思いたい)。MySQLでも同じような問題が起こるらしく、ActiveRecord に手を入れてる方も。

これが index ページを開いたところ。



あとはindexアクションを少し修正して、


# app/controllers/bookmarks_controller.rb
def index
bookmarks_all = Bookmark.find(:all, :order=>"created_at desc")

year = params[:year]
month = params[:month]
if year != nil && month != nil
first_of_month = Time.mktime(year.to_i, month.to_i, 1, 0, 0)
first_of_next_month = first_of_month.next_month.beginning_of_month
@bookmarks = Bookmark.find(:all, :conditions=>"created_at >= '#{first_of_month}' AND created_at < '#{first_of_next_month}'", :order=>"created_at desc")
else
# 作成日降順でリストを取得
@bookmarks = bookmarks_all
end


作成月のリストにリンクを張ります。

<div style="position: relative; float: left; margin-left: 10px">
<ul>
<% @created.each do |year, months| %>
<li>
<%= "#{year}年".force_encoding 'UTF-8' %>
<ul>
<% months.each do |month| %>
<!-- (作成月での)絞り込みのためのリンク -->
<li><%= link_to "#{month}月".force_encoding('UTF-8'), bookmarks_path(:year=>year, :month=>month) %></li>
<% end %>
</ul>
</li>
<% end %>
<li><%= link_to "all", bookmarks_path %></li>
</ul>
</div>


eRuby式の出力がなぜか ascii-8bit になるので、これもforce_encodingで無理やりUTF-8に。文字コードについてはまるっきり無知で、いつも付け焼刃になってしまう。基礎知識からつけないと。

現在のindexページはこうなっています。


indexアクションの中でクエリを2回(1回目は右ペインのため、2回目は左ペインのため)発行していて無駄があります。 右ペインは固定なので、左ペインだけ切り替えるように(Ajax化)するなり、工夫したいところ。


<< [Rails][習作] 簡易ブックマークアプリ (2)     [Rails][習作] 簡易ブックマークアプリ (4)>>

0 件のコメント:

コメントを投稿