今回は、以前実装したお気に入り登録(ブックマーク)に、いくつか機能を付け加えていきます。
前回:Ruby on Rails ~お気に入り登録(ブックマーク)機能の実装 http://qiita.com/wtb114/items/39367a39bd6a65701db7
実装するもの
1.ブックマークしたユーザー数の取得
2.ブックマークしたユーザーの一覧を取得
3.同じユーザーによるブックマークの重複登録を防ぐ
※「いいね!」などを実装する場合も、コピペで使用できます。
#1.修正前の確認
◆イベント一覧から興味のあるイベントをブックマークする機能です。
イベントは"Event"、ブックマークに使うモデルは"Clip"を使っています。
・ルート
resources :events do
member do
post "add", to: "clips#create"
end
end
resources :clips, only: [:destroy]
・モデル
class Clip < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
class Event < ActiveRecord::Base
has_many :clips
has_many :users, through: :clips
end
class User < ActiveRecord::Base
has_many :clips
has_many :events, through: :clips
end
・コントローラー
class ClipsController < ApplicationController
def create
@user_id = current_user.id
@event_id = Event.find(params[:id]).id
@clip = Clip.new(event_id: @event_id, user_id: @user_id)
if @event.save
redirect_to user_path(current_user)
end
end
def destroy
@clip = Clip.find(params[:id])
if @clip.destroy
redirect_to user_path(current_user)
end
end
end
・ビュー
<div>
<%= link_to "このイベントをクリップ", add_event_path(event), method: :post %>
</div>
#2.ルートの編集
resources :events do
member do
post "add", to: "clips#create"
get "show_clips" => "clips#show_clips"
end
end
resources :clips, only: [:destroy, :index]
後ほど、"show_clip"で、あるイベントをブックマークしたユーザーを表示させるビューを作ります。
get "show_clips" => "clips#show_clips" を :eventsにネストし記述することで、clipにeventのidを紐付けます。
$ rake routes
=>
show_clips_event GET /events/:id/show_clips(.:format) clips#show_clips
このようなルートができていると思います。
#3.モデルの編集
class Clip < ActiveRecord::Base
validates :user_id, :uniqueness => {:scope => :event_id}
belongs_to :user
belongs_to :event
end
Clipモデルに"validates :user_id, :uniqueness => {:scope => :event_id}"を記述します。
こうすることで、同じユーザーが同じイベントをブックマークできないようになります。(すでに保存されているClipのevent_idの場合に、user_idがユニークであるかどうか。)
"いいね!"機能など、重複して保存されないような機能を実装する場合にも使えます。
class Event < ActiveRecord::Base
has_many :clips
has_many :users, through: :clips
end
class User < ActiveRecord::Base
has_many :clips
has_many :events, through: :clips
end
#4.コントローラーの編集
class ClipsController < ApplicationController
def create
@user_id = current_user.id
@event_id = Event.find(params[:id]).id
@clip = Clip.new(event_id: @event_id, user_id: @user_id)
#以下、追記############################################################
if @clip.save
redirect_to clips_path(current_user)
else
redirect_to clips_path(current_user)
end
###############varidateの結果、ブックマークに成功した場合と失敗した場合の処理を記述
end
def destroy
@clip = Clip.find(params[:id])
if @clip.destroy
redirect_to user_path(current_user)
end
end
end
さらに2つのビューをつくるため。下記を追記。
"index"はユーザーがブックマークしたイベントを一覧で取得するページ。
"show_clips"は、あるイベントにブックマークしたユーザー一覧を取得するページ。
def index
@user = current_user
@clips = Clip.where(user_id: @user.id).all
end
def show_clips
@event = Event.find(params[:id])
@clips = Clip.where(event_id: @event.id).all
end
#5.ビューの編集
2つのビューを追加。
・ユーザーがブックマークしたイベントを一覧で取得するページ。
<h2>参加中のイベント</h2>
<% @clips.each do |clip| %>
<% event = Event.find(clip.event_id) %>
<div class="name3"><%= link_to event.event_name, event_path(event) %></div>
<div class="name2"><%= link_to "参加中のイベントから削除",clip_path(clip), method: :delete %></div>
<div class="name2">
<%= event.event_date.strftime("%Y-%m-%d %H:%M:%S") %>
</div>
<div class="name2">
<%= event.event_location %>
</div>
<br />
<% end %>
</div>
・あるイベントにブックマークしたユーザー一覧を取得するページ。
<h2>ユーザー一覧(<%= @clips.length %>人)</h2>
<% @clips.each do |clip| %>
<% @user_id = clip.user_id %>
<% user = User.find(@user_id) %>
<div class ="name2">
<%= link_to user.username ,user_path(user) %><br/>
</div>
<% end %>
以上で実装が完了しました。