第14回: ユーザーとタスクの関連づけ
2010/05/29
前々回と前回 で、Devise を使ったユーザー認証の仕組みをサンプルアプリケーションに組み込みました。
今回は、ユーザーとタスクの関連づけを行います。
ユーザーのシードデータ
データベースをリセットするたびに、手動でユーザー登録作業を行うのは面倒なので、ユーザーのシードデータを用意しましょう。
db/seeds.rb
を修正します。
table_names = %w(users tasks) (省略)
新規ファイル db/seeds/development/users.rb
を作成します。
%w(alpha beta gamma).each do |name| user = User.new( :email => "#{name}@example.com", :password => "#{name}...", :password_confirmation => "#{name}..." ) user.save user.confirm! end
user.save
でユーザーアカウントが登録されます。user.confirm!
でアカウントの確認手続きが完了します。
シードデータを投入します。
% rake db:reset
モデル間の関連づけ
まず、tasks
テーブルのマイグレーションファイルを修正し、整数型の user_id
カラムを追加します。
class CreateTasks < ActiveRecord::Migration def self.up create_table :tasks do |t| t.integer :user_id t.string :name (省略)
マイグレーションをやり直します。
% rake db:migrate:reset
User モデルと Task モデルの関連づけを行います。
app/models/user.rb
を修正します。
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :lockable and :timeoutable devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation has_many :tasks end
最後の行に has_many :tasks
を追加しています。
次に、app/models/task.rb
を修正します。
class Task < ActiveRecord::Base belongs_to :user scope :done, where(:done => true).order("due_date") scope :undone, where(:done => false).order("due_date") end
これで、User と Task が「1対多」の関係で結びつけられました。
tasks コントローラの修正
現在の index アクションは次のようになっています。
def index @task = Task.new @tasks = Task.undone.paginate(:page => params[:page], :per_page => 10) end
これを次のように修正します。
def index @task = Task.new @tasks = current_user.tasks.undone.paginate(:page => params[:page], :per_page => 10) end
この修正により、ログイン中のユーザー(current_user)の未完了タスクが 10 個ずつ表示されるようになります。
同様に done アクションを修正します。
def done @task = Task.new @tasks = current_user.tasks.done.paginate(:page => params[:page], :per_page => 10) render :action => 'index' end
続いて create アクションを修正します。現在のソースコードは次の通り。
def create @task = Task.new(params[:task]) if @task.save redirect_to :tasks else @tasks = Task.all(:conditions => { :done => false }, :order => "due_date") render :action => 'index' end end
else
の次の行は、ページネーションを導入したときに index アクションと同様に修正しておくべきでしたが、うっかりそのままになっていました。
修正後は、このようになります。
def create @task = Task.new(params[:task]) @task.user = current_user if @task.save redirect_to :tasks else @tasks = current_user.tasks.undone.paginate(:page => params[:page], :per_page => 10) render :action => 'index' end end
@task.user = current_user
の行が、ユーザーとタスクの関連づけを行っている部分です。
タスクのシードデータ
タスクのシードデータ db/seeds/development/tasks.rb
を修正します。
alpha = User.find_by_email('alpha@example.com') beta = User.find_by_email('beta@example.com') Task.create(:name => "Task 0", :due_date => Date.today, :done => true, :user => alpha) 1.upto(100) do |n| Task.create(:name => "Task #{n}", :due_date => n.days.from_now, :done => false, :user => n.even? ? alpha : beta) end
偶数番号のタスクは alpha ユーザーと、奇数番号のタスクは beta ユーザーと結びつけています。
シードデータを投入します。
% rake db:reset
ブラウザで動作確認
alpha ユーザーでログインします。
すると、偶数番号のタスクだけが表示されています。
今日の日付で「電球を買う」というタスクを追加します。
「Sign out」リンクをクリックしてログアウトし、beta ユーザーでログインすると、奇数番号のタスクだけが表示されます。