Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

認証の仕組みを用意する

Railsには様々な認証の仕組みがありますが、まずは基本的なものとして、
LoginGeneratorを使いたいと思います。

http://wiki.rubyonrails.com/rails/pages/HowToQuicklyDoAuthenticationWithLoginGenerator に基づき、ちょっとやり方を変えてあります。


1.用意

まず、LoginGeneratorをインストールします。

shell> gem install login_generator

2.次に、テスト用のプロジェクトを作成します。

shell> cd [普段プロジェクトを保存しているディレクトリ]
shell> rails myaccount
shell> mysql -u root --password
sql> create database myaccount_development
sql> use myaccount_development
sql>   CREATE TABLE users (
    id int(11) NOT NULL auto_increment,
    login varchar(80) default NULL,
    password varchar(40) default NULL,
    PRIMARY KEY  (id)
  );
sql> exit
shell> cd myaccount
shell> ruby script/generate login Account

※mysqlを前提としています。それ以外の方は、テーブルを
  
http://wiki.rubyonrails.com/rails/pages/HowToQuicklyDoAuthenticationWithLoginGenerator
  を参照に作成してください。また、mysqlの方も、rootのパスワードをconfig/database.yml
  に記載してください。

※ RadRailsをお使いの方は、
1. 新規作成して、
2. 該当するdatabase.ymlに該当するデータベースを作り、
   その中に


  CREATE TABLE users (
    id int(11) NOT NULL auto_increment,
    login varchar(80) default NULL,
    password varchar(40) default NULL,
    PRIMARY KEY  (id)
  );


  というテーブルを作成してから
3. Generatorsで "login" -> "Account"
  するという意味だと思ってください。

3.app/controllers/application.rb を変更します。


変更前:
# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
end


変更後:
# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
require_dependency "login_system"


class ApplicationController < ActionController::Base
  include LoginSystem
  model :user
end

ここまでで、アプリケーションが完成されます。
http://[あなたのIPアドレス]:3000/account/login
へアクセスしてみてください。ローカルホストアクセスだと、WindowsXP環境下では
正常に利用できないので、注意願います。(クッキーが保持されていないっぽい)

4.では、実際にサインアップしてみましょう。
私のIPアドレスは 192.168.80.1なので、
http://192.167.80.1:3000/account/signup
にアクセスします。サインアップ画面なので、ユーザーID、パスワードを記載すると
http://192.167.80.1:3000/account/welcome
というURLにリダイレクトされます。

その後ログアウト画面
http://192.167.80.1:3000/account/logout
をたたくとログアウトされ、

その後にログイン画面
http://192.167.80.1:3000/account/login
からログインできます。

5.次に、ログイン名を表示してみましょう。
ビューである
shell> cd [普段プロジェクトを保存しているディレクトリ] の後、
app/views/account/welcome.rhtml

    <h3>Welcome</h3>

    <h3>Welcome <%= @session['user'].login %></h3>
とします。 (@session[:user].loginではなぜかうまくいきませんでした。)

ログインしてから再び、
http://192.167.80.1:3000/account/welcome
を表示してみてください。

6.最後に、ほかのコントローラーから呼び出して見ましょう。

shell> cd [普段プロジェクトを保存しているディレクトリ]
shell> ruby script/generate controller test index test1 test2
とし、testコントローラーとView index, test1, test2を作成します。

test_controller.rbに

class AllMySecretsController < ApplicationController
   before_filter :login_required, :except => [ :index,test2]

   def show_one_secret
      ...
   end
end

と追加します。

これで、「index、test2」をのぞいたView (つまり、test1)にログインが要求されます。
反対に、「test1とtest2」のみログインを要求したい場合は
   before_filter :login_required, :except => [ :test1, :test2]
とします。

has_one について:効率的に作成/消去しましょう。

has_one によって、データベースを一対一にマップすることができます。
が、一対一にマップするだけであって、それらの作成/削除を自動で連携してくれる
わけではないみたいです。

モデル内にいくつかの行を挿入すると、これらの連携ができて便利です。

例: 以下の2つのテーブルがあったとします。
mysql> describe users;
+----------+--------------+------+-----+-------------------+----------------+
| Field    | Type         | Null | Key | Default           | Extra          |
+----------+--------------+------+-----+-------------------+----------------+
| id       | int(11)      | NO   | PRI |                   | auto_increment |
| login    | varchar(225) | NO   |     |                   |                |
| password | varchar(225) | NO   |     |                   |                |
| updated  | timestamp    | YES  |     | CURRENT_TIMESTAMP |                |
+----------+--------------+------+-----+-------------------+----------------+
4 rows in set (0.00 sec)


mysql> describe profiles;
+---------+--------------+------+-----+-------------------+----------------+
| Field   | Type         | Null | Key | Default           | Extra          |
+---------+--------------+------+-----+-------------------+----------------+
| id      | int(11)      | NO   | PRI |                   | auto_increment |
| email   | varchar(225) | NO   |     |                   |                |
| blog    | text         | NO   |     |                   |                |
| picture | text         | NO   |     |                   |                |
| user_id | int(11)      | NO   |     | 0                 |                |
| updated | timestamp    | YES  |     | CURRENT_TIMESTAMP |                |
+---------+--------------+------+-----+-------------------+----------------+
6 rows in set (0.00 sec)

usersはLoginGeneratorにて必要となる基本テーブル、profilesは
そのテーブルに入りきらない情報を追加しています。


userに対して、profilesを追加する際は、

model/profiles.rb には
  belongs_to :user 
model/user.rbには
  has_one :profile

を追加するというのが流儀ですが、ここで、user.rbには、上記の代わりに
  has_one :profile
  before_destroy :delete_profile
  def delete_profile
    self.profile.destroy
  end
と追加すると、user.rbにて削除される際に、profileも同時に削除されます。

追加の際のことも考えると、
  has_one :profile
  before_create :create_profile
  before_destroy :delete_profile
  def create_profile
    profile = Profile.new
    self.profile = profile
  end
  def delete_profile
    self.profile.destroy
  end

とすればOKです。

※ただし、トランザクションの一貫性に関しては疑問が残ります。。

補足>>

Paginator :複雑なPaginator

リストを例えばGoogleの検索結果のように表示したい際、
pagenator は非常に便利です。しかし、デフォルトの
ページネーターはちょっと複雑なことをやろうとすると
厄介に感じます。


例えば、「comment」というデータをgenerate scaffold
にて作成すると、comment_controller.rbに


  def list
    @comment_pages, @comments = paginate :comments, :per_page => 10
  end


と作成されます。しかし、「ある特定の人のコメント」
を考えようとすると、この表示では厄介です。


LoginGeneratorにて作られた「user」にこのコメントがhas_one
されているとしましょう。このように書きます。


  def list
    comments = User.find(@session['user'].id).comments;
    @comment_pages = Paginator.new self, comments.count, 10, @params['page']
    @comments = comments.find  :all,
                            :limit  => @comment_pages.items_per_page,
                            :offset => @comment_pages.current.offset
  end


なお、Viewはscaffoldのデフォルトでは


<%= link_to 'Previous page', { :page => @user_pages.current.previous } if @user_pages.current.previous %>
<%= link_to 'Next page', { :page => @user_pages.current.next } if @user_pages.current.next %>


と書きますが、


<%= pagination_links(@user_pages) %>


と書くとGoogleのように 1,2,…,10と書けます。

グラフを使用する : Sparklines

(文章を作成中です)

Sparklinesはグラフライブラリです。Ruby on Railsから
generatorを通じて利用することができます。

1. インストール

gem install sparklines
gem install sparklines_generator
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。