SAHARA

Railsで簡単なブックマーク機能を作る

更新回数:3回 | 2015/07/18更新
編集者:Thumb img 0
 Ruby on Railsで簡単にブックマーク機能を作る方法を書きます。
概要を書くと、ユーザーがブックマークのアイコンをクリックするとそのページがブックマークされ、もう一度クリックするとブックマークを外すような仕組みを作ります。
  まずはDeviseというログイン機能を作るgemを使いユーザーモデルを作成し、次に記事モデル、そしてブックマークモデルを作り、最後にブックマーク機能を搭載します。

ユーザーモデルを作る

 会員制のwebサイトを想定し、まずはログイン機能などのユーザー情報に関連するシステムを作っていきます。
 まずはDeviseの導入からしていきます。

まず新しくRailsアプリケーションを作ります。
$ rails new BookmarkApp

Deviseを導入します。
Gemfile
gem 'devise'

$ bundle install

Deviseをインストール。
$ rails generate devise:install

ログインエラーを表示するために、application.html.erbに以下を追加します。
application.html.erb
<body>
   <p class="notice"><%= notice %></p>
   <p class="alert"><%= alert %></p>
   <%= yield %>
</body>

Devise経由でUserモデルを作ります。
$ rails generate devise User

データーベースに反映。
$ rake db:migrate

これで、ユーザーモデルとログイン機能を作成できました。


記事モデルを作る

 ブックマークされる記事を作ります。
$ rails g scaffold Post title body:text

$ rake db:migrate

ホーム画面を記事一覧に紐付けます。
routes.rb
Rails.application.routes.draw do
 resources :posts
 devise_for :users
 root "posts#index"
end

この状態でサーバーを立ててしっかり動作するか見ます。
$ rails s
間違いが無ければ、記事の作成ができるようになっています。


Bootstrapの導入

 見栄えを少し良くするためにBootstrapを導入してみます。
Gemfile
gem "bootstrap-sass"

application.cssをapplication.scssに名前を変更し、以下を追加してください。
application.scss
@import "bootstrap-sprockets";
@import "bootstrap";

ナビゲーションバーを設置します。
application.html.erb

<body>
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">BookmarkApp</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav navbar-right">
        <% if user_signed_in? %>
            <li><%= link_to current_user.email, '#' %></li>
            <li><%= link_to 'ログアウト', destroy_user_session_path, method: :delete %></li>
        <% else %>
            <li><%= link_to '登録', new_user_registration_path %></li>
            <li><%= link_to 'ログイン', new_user_session_path %></li>
        <% end %>
      </ul>
    </div>
    <!-- /.navbar-collapse -->
  </div>
  <!-- /.container-fluid -->
</nav>

<p class="notice"><%= notice %></p>

<p class="alert"><%= alert %></p>

<div class="container">
  <%= yield %>
</div>

</body>

サーバーをリスタートして確認してください。
これでナビゲーションバーのリンクからログイン・ログアウトができるようになりました。



ブックマークボタンを作る

 各記事のブックマーク機能を作るために、まずは見た目から作っていこうと思います。まずは各記事上部にブックマークアイコンを設置します。font-awesome-railsというアイコンをまとめたgemがあるのでそれを利用します。

gemfile
gem "font-awesome-rails"

$ bundle install

application.scss
@import "font-awesome";

記事にブックマークアイコンを設置します。
app/views/posts/show.html.erb
<p id="notice"><%= notice %></p>
<!--追加-->
<p>
  <%= link_to '#', id: 'bookmark-link' do %>
      <i class="fa fa-bookmark fa-2x"></i>
  <% end %>
</p>

<p>
  <strong>Title:</strong>
  <%= @post.title %>
</p>

これで、下の画像のようにブックマークアイコンが表示されたと思います。
Image title
 font-awesomeでは、<i>タグに'fa-bookmark'クラスを付けるとブックマークアイコンが表示されます。そして、そこにプラスして'fa-bookmark-o'クラスを付け加えると中身がくり抜かれたブックマークアイコンが表示できます。これを使い、ブックマークされているかどうかを表示することが出来ます。
 まずは実際にブックマークされているかどうかは別にしてブックマークアイコンをクリックすると表示が切り替わる仕組みをJavaScriptで書いていきます。
 アイコンをクリックすると、<i>タグのクラス'fa-bookmark-o'をつけたり引いたりするようにします。

app/assets/javascripts/bookmarks.coffee
bookmark_icon = ->
  $("#bookmark-link").click ->
    $(this).children('i').toggleClass('fa-bookmark-o')

$(document).on('page:change', bookmark_icon)
これで、クリックすると表示が切り替わるようになりました。
次は、ブックマークの内部を作ります。


ブックマーク機能を作る

 ユーザーのブックマークを保存するためにモデルを作ります。ブックマークモデルは、どのユーザがどの記事をブックマークしたかという情報が必要なので以下のようにブックマークモデルを作ります。
$ rails g model bookmark user:references post:references

$ rake db:migrate

ブックマークモデルをユーザーモデルと記事モデルに紐付けます。

app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  #追加
  has_many :bookmarks
end

app/models/post.rb
class Post < ActiveRecord::Base
  has_many :bookmarks
end


次にブックマークコントローラーを作ります。
app/controllers/bookmarks_controller.rb
class BookmarksController < ApplicationController
  def toggle
    post_id = params[:post_id]
    user_bookmarks = current_user.bookmarks
    if user_bookmarks.exists?(post: post_id)
      user_bookmarks.where(post: post_id).destroy_all
    else
      user_bookmarks.create(user: current_user, post: Post.find(post_id))
    end
    render :nothing => true
  end
end

toggleアクションを作成しています。ブックマークをしていない場合はブックマークし、している場合はブックマークを外します。
 そして、ブックマーク操作したあとはJavaScriptで表示を変更するので"render :nothing => true
を指定し、何もrenderしない設定をしています。

次にブックマークアイコンのリンク先に上のメソッドを紐付けます。
config/routes.rb
Rails.application.routes.draw do
  #追加
  resources :posts do
    get "bookmarks/toggle"
  end
end

views/posts/show.html.erb
#リンク先を設定。remote: :trueも設定。
<p>
  <%= link_to post_bookmarks_toggle_path(@post) , id: 'bookmark-link', remote: true do %>
      <i class="fa fa-bookmark fa-2x"></i>
  <% end %>
</p>

これで、ブックマークをつけたり外したりが出来るようになりました。
しかし、viewで
<i class="fa fa-bookmark fa-2x"></i>
というふうに指定してしまっているので、ページを開くと常にブックマークアイコンが黒塗りされてしまっています。ブックマークしていれば黒塗り、していなければ白塗りとするためにhelperを使用しブックマーク状況に応じて表示するようにします。

app/helpers/bookmarks_helper.rb
module BookmarksHelper
  def bookmark_icon(post, user)
    if user
      if user.bookmarks.exists?(post: post)
        '<i class="fa fa-bookmark fa-2x"></i>'
      else
        '<i class="fa fa-bookmark fa-bookmark-o fa-2x"></i>'
      end
    end
  end
end

app/views/posts/show.html.erb
<p>
  <%= link_to post_bookmarks_toggle_path(@post) , id: 'bookmark-link', remote: true do %>
      <!--変更-->
      <%=raw bookmark_icon(@post, current_user) %>
  <% end %>
</p>

これでログインしていればブックマークアイコンが表示され、ブックマークしていなければ白塗り、ブックマークしていれば黒塗りで表示されるようになりました。


  以上で、ブックマーク機能が全て完成しました。
このサイト「さはら」でも同じように実装しているので、それをまとめた形となりました。
もし間違いがあれば、訂正お願いします。



発言はまだありません。
発言するにはログインもしくは、会員登録をしてください。