前回の記事では、
リソース設計
前回作成したブックマークアプリケーションは、
機能 | HTTP Method | URI |
---|---|---|
リンクの作成 | POST | /links |
リンクの表示 | GET | /links/:id |
リンクの変更 | PUT | /links/:id |
リンクの削除 | DELETE | /links/:id |
つまり、
ソーシャルブックマークと名乗っているにもかかわらず、
これらを踏まえて、
機能 | HTTP Method | URI |
---|---|---|
リンクの作成 | POST | /:username/ |
リンク一覧表示 | GET | /:username/ |
リンクの表示 | GET | /:username/ |
リンクの変更 | PUT | /:username/ |
リンクの削除 | DELETE | /:username/ |
タグ一覧表示 | GET | /:username/ |
タグの表示 | GET | /:username/ |
Routing map.resourceふたたび
前説で設計したリソースに対する、
具体的なコードに入る前に、
特に、
:path_prefix
リソースがネストする場合に、
map.resouces :links, :path_prefix => ':username'
ここで指定した、
:has_many, :has_one
Routingのネストを行い、
今回作成しているブックマークアプリケーションでは
map.resources :users, :has_many => [:links, :tags]
ユーザリソースに、
機能 | HTTP Method | URI |
---|---|---|
リンクの作成 | POST | /users/:id/ |
リンクの表示 | GET | /users/:id/ |
タグの表示 | GET | /users/:id/ |
GET /users/1/links/6.xml
:member
CRUD以外、
例として、
map.resouces :link, :member => {:hide => :put}
PUT /links/1/hide
なお、
miniciousのRouting定義
これらの機能を用いた、
ActionController::Routing::Routes.draw do |map|
map.home '', :controller => 'sessions', :action => 'destroy'
map.resources :links , :path_prefix => '/:username'
map.resources :tags , :path_prefix => '/:username'
map.resource :session
map.login 'login', :controller => 'sessions', :action => 'new'
map.logout 'logout', :controller => 'sessions', :action => 'destroy'
end
ActiveResource
ここで、
ActiveResource とは、
また、
ActiveResourceにできること
ActionWebServiceの代わりとして導入されたActiveResourceですが、
今回作成したアプリケーションは、
ActiveResouceの利用例
それでは、
% rails minicious-es
つづいて、
class Link < ActiveResource::Base
self.site = 'http://user:user@localhost:3000/'
self.prefix = '/user/'
end
これだけで、
コードを見ていきましょう。まず、
つづいて、
それでは、
ActiveRecord | ActiveResource | URI |
---|---|---|
Link. | Link. | GET http:// |
Link. | Link. | GET http:// |
Link. | Link. | GET http:// |
Link. | Link. | POST http:// |
ユーザ名
>> Link.create({:url=>"http://www.example.com", :tag_names=>"test example"})
=> #<Link:0xb795650c @prefix_options={}, @attributes={"updated_at"=>Tue May 06 14:00:44 UTC 2008, "url"=>"http://www.example.com", "notes"=>nil, "id"=>20, "tag_names"=>"test example", "user_id"=>1, "created_at"=>Tue May 06 14:00:41 UTC 2008}>
いかがでしょうか。こういった形で、
最終的なアプリケーションコード
ここまでの機能を含む最終的なコードの簡単な解説をしていきます。
モデル
まずは、
class Link < ActiveRecord::Base
has_many :assorts
has_many :tags, :through=>:assorts
belongs_to :user
def tag_names=(value)
Tag.transaction do
self.save
tag_ids = self.tags.map(&:id)
self.tags.delete(Tag.find(tag_ids)) if self.tags
tags = value.split(" ")
tags.each do |t|
self.tags << Tag.find_or_create_by_name(t)
end
end
end
def tag_names
self.tags.map(&:name).join(" ")
end
def self.create_with_user(condition, current_user)
@link = Link.create(condition)
@link.user = current_user
@link
end
def self.find_by_user_name_and_tag_id(user_name, tag_id)
Link.find_by_sql([<<-SQL, {:user_name => user_name, :tag_id => tag_id}])
SELECT
links.*
FROM
users,
tags,
assorts,
links
WHERE
users.login = :user_name
AND
links.user_id = users.id
AND
assorts.link_id = links.id
AND
tags.id = :tag_id
AND
tags.id = assorts.tag_id
SQL
end
end
リンクを管理する、
代入メソッドtag_
また自身以外のユーザによる変更は発生しないはずですが、
取得メソッドtag_
find_
class Tag < ActiveRecord::Base
has_many :assorts
has_many :links, :through=>:assorts
def self.find_by_user_name(user_name)
Tag.find_by_sql([<<-SQL, {:user_name => user_name}])
SELECT
count(tags.name) cnt
,tags.*
FROM
users,
tags,
assorts,
links
WHERE
users.login = :user_name
AND
links.user_id = users.id
AND
assorts.link_id = links.id
AND
tags.id = assorts.tag_id
GROUP BY tags.name
SQL
end
end
タグを管理するTagモデルのfind_
コントローラ
つづいて、
class LinksController < ApplicationController
before_filter :login_required , :only => [:new, :create, :edit, :update, :destroy]
# 以下省略
end
リンクURIをコントロールするLinksControllerです。before_
上のコード例以外の修正として、
ERb View
最後に、
<table width="100%">
<tr>
<% if @links.size > 0 %>
<td width="70%">
<h1>links</h1>
<table>
<% for link in @links %>
<tr>
<td><%= link_to link.url, link.url %></td>
<% if current_user_id == params[:username] %>
<td><%= link_to 'edit', edit_link_path(params[:username], link) %> /</td>
<td><%= link_to 'destroy', link_path(params[:username], link), :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<tr>
<td colspan="3"><small><%=h link.notes %></small></td>
</tr>
<tr>
<td colspan="3"><small>to <%=h link.tag_names %></small></td>
</tr>
<% end %>
</table>
</td>
<% end %>
<% if @tags.size > 0 %>
<td width="30%" valign="top" bgcolor="#dddddd">
<h1>Tags</h1>
<table>
<% for tag in @tags %>
<tr>
<td><%= tag.cnt%> <%= link_to tag.name, tag_url(params[:username], tag) %></td>
</tr>
<% end %>
</table>
</td>
<% end %>
</tr>
</table>
<br />
リンク一覧を表示する、
ここではURIの変更に関連するlink_
index.
画面イメージとソースアーカイブ
次の画面は、

次の画面は、

ソースコードアーカイブ
以下が今回改良したminiciousソースアーカイブです。
ちなみに最終段階においてもminiciousにはユーザ管理の画面はありません。今回作成したminiciousは、
まとめと展望と次回予告
今回は、
今回作成したアプリケーションは、
例えば、
残念ながら、
Railsによるアプリケーション作成の実例はこの辺にしまして、