ちょっとしたSNSもどきをつくってみた(1)
SNSもどきを作る
ログイン機能は必須だろう。restful_authenticationプラグインがデファクトスタンダードらしい。メールを使ってサインアップもできたりするらしいけど、ちょっとソースを追っかけるレベルでないので後回し
(http://d.hatena.ne.jp/tsimo/20080323/1206277929)をみてやりました
新しくプロジェクトを作る。
$ rails rails_sns_1
プラグインをインストールする
$ script/plugin install git://github.com/technoweenie/restful-authentication.git
生成
$ script/generate authenticated user sessions $ db:migrate $ script/server
あとは適当にテーブルを作っておく
$script/generate scaffold post user_id:integer title:string text:text
どんなものが作られたか。まずconfig/routes.rb
# ログイン画面用。login_path map.login 'login', :controller => 'sessions', :action => 'new' # ログアウト用。logout_path map.logout '/logout', :controller => 'sessions', :action => 'destroy' # サインアップ画面。signup_path map.signup '/signup', :controller => 'users', :action => 'create' # 登録。register_path map.register '/register', :controller => 'users', :action => 'new' # ユーザリソースとセッションリソース map.resources :users map.resource :session
- sessionsコントローラはログイン(セッション生成)/ログアウト(セッション破棄)用
- usersコントローラはサインアップ用(登録画面/登録処理)
- 後ろのmap.resource(s)は拡張用でしょうか。使ってないよね?
- sessionはシングルトンリソースとして設定されている。そうやって使うのか
- RESTfulとうたうなら、/logoutとかはアウト?すなおに/sessionをDELETEするほうがそれっぽい?
コントローラ。SessionsControllerとUsersControllerに書いてある下のinclude文をApplicationControllerに移動した
include AutuenticatedSystem
- このコントローラでは認証システムを使うよ、ということらしい。ApplicationControllerに書けば全体に適用される
- また、before_filter :login_required とするとログインしてない場合は自動的にログインページ(/sessions/new)に飛ばしてくれる
- ApplicationControllerに書いといて、不要なところだけskip_before_filterするのが楽チンそう
モデル。userのみ。
- おおざっぱに、includeしてるところ、validateしてるところ、と追加のクラスメソッド(authenticate)に分かれる
ここまでの動きはなんとなくわかった。ので、今回作るもの
- レイアウトは、左メインコンテンツ。右にアカウント情報(ログインしてなかったらログインフォーム)
- トップページには、すべてのユーザのpostを新しい順に並べる(ついでにコメント数も)
- users/1/postsでそのユーザが書いたpostが見えます
- postはそのユーザしか編集できません
- profileテーブルとか作って、さらに画像とかもアップロードできたらいいな
まずは関連
class User < ActiveRecord::Base 〜いろいろ省略〜 has_many :posts end class Post < ActiveRecord::Base belongs_to :user end
レイアウト
posts.html.erbをリネームしてapplication.html.erbとする(つかいまわし用)。
ナビゲーションバーの中身を共通化したくて、こんなことしたんだけど、いいのかな?
<!-- ナビゲーション --> <div id="navi"> <%= render(:partial => 'layouts/navi') -%> </div>
パーシャルの中身。logged_in?でログイン中かどうかがわかる
正直、あまりきれいじゃない。。
<div class="block"> <%- if logged_in? -%> <h3>ログイン中</h3> <p>こんにちは、<%=h current_user.name %>さん</p> <%- else -%> <h3>ログインしてください</h3> <% form_tag session_path, :class => "mini_login_form" do %> <%= render :partial => 'sessions/form' -%> <%- end -%> <%- end -%> </div>
ルーティングを変えました。
/users/1 で1ばんさんのトップページ
/users/1/posts で1ばんさんのpostの一覧ページにいくようなイメージです
map.resources :users do |user| user.resources :posts end
自分いがい書けないようにするために、以下のようにした。いいのかな?
def auth_check unless logged_in? && @current_user == @user flash[:error] = "あなたにはこの日記への書き込み権限がありません" redirect_to user_posts_path(@user) end end
before_filterでfalseを返してもその後の処理は継続される。falseでチェインを停止するのは、1.xの仕様らしい。だまされた。。
自分いがいの場合は「編集」ボタンとかを表示しないようにするために、ヘルパーメソッドを追加した。おなじチェックなのに、ちょっと無駄な気が。
def writable? logged_in? && (current_user == @user) end