Rails + Cicindelaでレコメンデーション付ウェブサイトの構築(1)
目次
- ユーザ認証付Railsアプリの構築 ←いまここ
- RailsアプリにCicindelaインタフェースを実装
- Cicindelaの設定とバッチ処理設定
先日Sapporo.rbで黙々と読書した成果として、Ruby on RailsのアプリにCicindelaのレコメンデーション機能をつけることができました。そんなわけで何回かに分けて説明していきます。
まずはRailsアプリを作ります。お題としてはソーシャルブックマークサービスにしてみます。ブックマークアプリはRailsの課題曲みたいなもので、慣れた人なら10分で作れます。今回はそれに加えてユーザごとにブックマークできるよう、ログイン認証などの機能拡張が必要になります。
完成版のソースコードはgithubにて公開しています。
Railsアプリケーションの作成
今回の環境としてはこんな感じです。
OS: Ubuntu 8.04
Ruby: 1.8.6
Ruby on Rails: 2.2.2
MySQL: 5.0.51
とりあえずプロジェクト作成。
rails bookmark -d mysql cd bookmark
データベースの作成
mysql -uroot -ppass -e "create database bookmark;"
管理者名、パスワードは適当に読み替えてください。
config/database.ymlを編集。
database: bookmark username: root password: pass
認証プラグインのインストール
ログイン認証はrestful_authenticationを使うことにします。
script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/ script/generate authenticated user sessions
app/controllers/users_controller.rbを編集して以下の行をコメントアウト。
#include AuthenticatedSystem
その代わりapp/controllers/application.rbに以下の行を追加。
include AuthenticatedSystem
これだけで認証機能ができてしまいます、簡単簡単。プログラムで制御したり表示する場合などはcurrent_user.idでユーザIDが、current_user.loginでユーザ名が取得できます。
アプリケーション雛形の生成
さて、テーブル設計ですが、こんな感じ。ひとつのウェブページに対して複数の人がブックマークしてコメントできるようにします。レコメンデーションが本題なのでアプリの機能としては必要最小限で。
script/generate scaffold Webpage url:string title:string script/generate scaffold Bookmark user_id:integer webpage_id:integer comment:string
User関係はrestful_authenticationが作ってくれているのでテーブルもクラスも自作する必要はありません。
テーブル間の関連設定
app/models/bookmark.rbを編集し、belongs_toを追加。
class Bookmark < ActiveRecord::Base belongs_to :user belongs_to :webpage
app/models/user.rbを編集、has_manyを追加。
class User < ActiveRecord::Base has_many :bookmarks
app/models/webpage.rbを編集、has_manyを追加。
class Webpage < ActiveRecord::Base has_many :bookmarks
テーブル作成
rake db:migrate
アクセス制限設定
login_requiredを追加することで、ログアウト状態の時はアクセスできなくなります。
app/controllers/bookmarks_controller.rb、app/controllers/webpagess_controller.rbを編集
before_filter :login_required
コントローラの設定
こんな感じ。
app/controllers/bookmarks_controller.rb(一部)
class BookmarksController < ApplicationController before_filter :login_required def index @bookmarks = Bookmark.find_all_by_user_id(current_user.id, :order => 'updated_at desc', :include => :webpage) end def create @webpage = Webpage.find_by_url(params[:webpage][:url]) if @webpage.nil? @webpage = Webpage.new(params[:webpage]) unless @webpage.save render :action => "new" end end @bookmark = Bookmark.find_by_user_id_and_webpage_id(current_user.id, @webpage.id) if @bookmark.nil? @bookmark = Bookmark.new(:user_id => current_user.id, :webpage_id => @webpage.id) end @bookmark.comment = params[:bookmark][:comment] if @bookmark.save flash[:notice] = 'Bookmark was successfully created.' redirect_to(bookmarks_url) else render :action => "new" end end (省略)
indexメソッドでは、自分のブックマークだけを更新順に取得しています。
createメソッドでは、新規ブックマークしたときに該当するwebpagesのレコードがなかったら(まだ誰もそのページをブックマークしていなかったら)、bookmarksテーブルだけでなくwebpagesにもレコードを追加するようにしています。
ビューの設定
まあ適当にこんな感じで。
app/views/bookmarks/index.html.erb
<h2><strong><%=h current_user.login %></strong>さんのブックマーク</h2> <% for bookmark in @bookmarks %> <h1><%= link_to bookmark.webpage.title, :controller => 'webpages', :action => 'show', :id => bookmark.webpage_id %></h1> <span class="url"><%= link_to bookmark.webpage.url, bookmark.webpage.url %></span><br /> <%=h bookmark.comment %><br /> <%= link_to '編集', edit_bookmark_path(bookmark) %> <%= link_to '削除', bookmark, :confirm => 'Are you sure?', :method => :delete %> <% end %>
新規ブックマーク画面ではwebpageの情報も入力するようにします。
app/views/bookmarks/new.html.erb
<h1>新規ブックマーク</h1> <% form_for(@bookmark) do |f| %> <%= f.error_messages %> <p> <%= label :webpage, "Title" %><br /> <%= text_field :webpage, :title %> </p> <p> <%= label :webpage, "URL" %><br /> <%= text_field :webpage, :url %> </p> <p> <%= f.label :comment %><br /> <%= f.text_field :comment %> </p> <p> <%= f.submit "Create" %> </p> <% end %> <%= link_to 'Back', bookmarks_path %>
ウェブページ詳細画面(冒頭のスクリーンショット)では、このページをブックマークしているユーザの一覧を表示します。後でここにレコメンデーション一覧も追加する予定。
app/views/webpages/show.html.erb
<h1>ブックマーク詳細</h1> <h1><%=h @webpage.title %></h1> <span class="url"><%= link_to @webpage.url, @webpage.url %></span> <br /> <h3>◆このページをブックマークしているユーザ</h3> <table> <% for bookmark in @bookmarks %> <tr> <td><strong><%=h bookmark.user.login %></strong></td> <td><%=h bookmark.comment %><br /></td> </tr> <% end %> </table> <%= link_to 'Edit', edit_webpage_path(@webpage) %> | <%= link_to 'Home', bookmarks_path %>
それ以外にもリンク先の変更だとか、スタイルシート設定とかもろもろありますがここでは省略。
起動します。
script/server
できた。(/localhost:3000/bookmarks)
長くなったので今回はここまで。次回はCicindela側の設定と、Railsとの連携について書く予定です。