地方でリモートワーク in Iwate

東京の受託開発会社でリモートワークしてます。

Railsで多対多のアソシエーションで中間テーブルに外部キー以外のカラムにアクセスする方法

スポンサーリンク

f:id:ihatov08:20160728001100j:plain

Railsで多対多のアソシエーションで中間テーブルに外部キー以外のカラムにアクセスする方法です。

likesテーブルの外部キーは今回の場合user_idproduct_idです。外部キー以外にもlike_typeをもたせています。 このlike_typeカラムですが、0の場合はunlike,1の場合はlikeとして管理したいと思っています。like_typeはenumで管理しています。

今回は各ユーザーがlikeしたproduct一覧を取得しつつ、likesテーブルのlike_typeカラムもviewで表示したいと思います。

rice_curry_table%20(9).pdf

テーブル定義f:id:ihatov08:20160728001100j:plain

  create_table "likes", force: :cascade do |t|
    t.integer  "product_id", limit: 4, null: false
    t.integer  "user_id",    limit: 4, null: false
    t.integer  "like_type",  limit: 4, null: false
    t.datetime "created_at",           null: false
    t.datetime "updated_at",           null: false
  end

  create_table "users", force: :cascade do |t|
    t.string   "name",                     limit: 255,               null: false
    t.string   "email",                    limit: 255,               null: false
    t.datetime "created_at",                                         null: false
    t.datetime "updated_at",                                         null: false
  end

  create_table "products", force: :cascade do |t|
    t.string   "name",                limit: 255,   null: false
    t.text     "description",         limit: 65535, null: false
    t.datetime "created_at",                        null: false
    t.datetime "updated_at",                        null: false
  end

アソシエーション

class User < ActiveRecord::Base
  has_many :likes
  has_many :like_products, through: :likes, source: :product
end
class Product < ActiveRecord::Base
  has_many  :likes
  has_many :like_users, through: :likes, source: :user
end
class Like < ActiveRecord::Base
  belongs_to :product
  belongs_to :user
  enum like_type: [ :dislike, :like]
end

ルーティング

今回はユーザーがlikeしたproduct一覧を表示するので以下のようなルーティングを設定しています。

  resources :users do
    member do
      get 'likes'
    end
  end

controller

  def likes
    @user = User.find(params[:id])
    @products = @user.like_products
  end

viewでアクセスする方法

each文をネストしています。子ネストでproduct.likesだけにすると親ネストで取得したproductsのidを持つlikesテーブルのレコードをすべて取得してきてしまいます。 そのためwhereで取得してきたいuserを絞り込んでいます。

<% @products.each do |product| %>
  <% product.likes.where(user_id: @user.id).each do |like| %>
    <%= product.name %>
    <%= like.like_type %>
  <% end %>
<% end %>

もっときれいに書きたい

each文をネストしているし、もっとうまく、きれいに書きたいです。他に良い方法をご存知の方がいらっしゃいましたら教えてください!

改訂3版 基礎 Ruby on Rails 基礎シリーズ

改訂3版 基礎 Ruby on Rails 基礎シリーズ