Labyrinth of Wisdom

-This is My Archive-


お気に入り機能サンプル①

Ruby on Railsで、ログインしたユーザが本一覧の中から気になる本をお気に入りに登録・削除するというサンプルを作っていきたいと思います!

ちょっと長くなりそうなので二回に分けて書いていきたいと思います。

Rails 4.25 ruby 2.23

今回の機能はこちらの記事からの続きになっています。

テーブル設計

中間テーブルを作る事で、テーブル同士は多対多の関係を結ぶことができます。
関係を結んだ後は、お互いのテーブルから他方にアクセスできるようになります。
一人のユーザは複数のお気に入りの本を持ち、一冊の本は複数のユーザにお気に入り登録されています。

1 多 / 多 1
User Favorite(中間テーブル) Book

モデル

  • Favoriteモデル作成

    Favoriteモデルを作成します。コマンドラインで下記コマンドを入力します。
    カラムの設定が複雑なので、後ほどマイグレーションファイルに直接書き込みます。

rails g model favorite
  • app/models/favorites.rb

    belongs_toでusers、booksテーブルとそれぞれ1対多の関係を結びます。

class Favorite < ActiveRecord::Base
    belongs_to :user #User:Favorite => 1:多
    belongs_to :book #Book:Favorite => 1:多
end
  • app/models/users.rb

    has_manyでfavaritesテーブルと1対多の関係を結びます。
    has_manythrough:を使い、favoritesテーブルを通してbooksテーブルと多対多の関係を結びます。
    ここでbooks複数なことに注意しましょう。

class User < ActiveRecord::Base
    has_many :favorites #User:Favorite => 1:多
    has_many :books, through: :favorites
    #クラスメソッド省略
end
  • Bookモデル作成

    Bookモデルを作成します。コマンドラインで下記コマンドを入力します。

rails g model book name:string price:integer
  • app/models/books.rb

    先ほどと同様に、has_manyでfavaritesテーブルと1対多の関係を結びます。
    has_manythrough:を使い、favoritesテーブルを通してusersテーブルと多対多の関係を結びます。
    ここでもusers複数なことに注意しましょう。

class Book < ActiveRecord::Base
    has_many :favorites #User:Favorite => 1:多
    has_many :users, through: :favorites
end

これでひとまずモデル同士の紐づけは完了しました。

マイグレーションファイル/テーブル作成

favoritesテーブルを作っていきます。

  • db/migrate/yyyymmddhhmmss_create_favorites.rb

    カラムの設定をしてなかったので、マイグレーションファイルに直接記述していきます。

class CreateFavorites < ActiveRecord::Migration
  def change
    create_table :favorites do |t|
      t.references :user, null:false #外部キー
      t.references :book, null:false #外部キー
      t.timestamps null: false
    end

    add_index :favorites, :user_id #インデックス
    add_index :favorites, :book_id #インデックス
  end
end

次にマイグレーションファイルを実行してテーブルを作成します。

rake db:migrate

これでfavoritesテーブルができました。テーブル同士の紐づけも完了しました。

シードデータ

  • db/seeds.rb

    シードデータに適当なデータを準備しておきます。

Book.create!(name: "マギ", price: 500)
Book.create!(name: "シンドバッドの冒険", price: 600)
Book.create!(name: "海皇紀", price: 580)

User.create!(name: "アラジン", email: "magi@hoge.com", password: "magimagi")

Favorite.create!(user_id: 1, book_id: 1)
Favorite.create!(user_id: 1, book_id: 3)

テーブルに反映します。

rake db:reset

ルーティング

ユーザへのルーティングを行います。

  root "top#index"
  resource :sessions, only: [:new, :create, :destroy]
  resources :users #追加分

コントローラ

コントローラを作成していきます。

  • app/controllers/users_controller.rb

    今回は特定のユーザの詳細ページにアクセスすると、ユーザの登録したお気に入り一覧が出る所まで実装します。
    ※今回の機能とは直接関係ないので、ユーザ一覧のコード等は省略します。

def show
    @user = User.find(params[:id])
    #特定のユーザーが登録したお気に入りを全て取得する
    @favorites = Favorite.where("user_id = ?", @user)
end

ビュー

  • app/views/user/show.html.erb

    ユーザ詳細ページにユーザが登録したお気に入りの本一覧を表示します。
    @user.booksで特定のユーザが持つお気に入りの本にアクセスできます。

    <h3>お気に入りの本</h3>
    <table>
      <thead>
          <tr>
            <th>削除</th>
            <th>タイトル</th>
            <th>価格</th>
          </tr>
      </thead>
      <tbody>
        <% @user.books.each do |book| %>
          <tr>
            <td><%= book.name %></td>
            <td><%= book.price %></td>
          </tr>
        <% end %>
      </tbody>
    </table>

これで各ユーザ別お気に入りリストが見れるようになりました。 次回はお気に入りの登録・削除を実装していきます。

参考

Rails4で多対多のリレーションをモデルに実装する - Rails Webook