0

私はこのアプリケーションで立ち往生しています ) 私には 3 つのモデルがあります - ユーザー、写真、いいね ユーザーはログインして写真を表示し、それらに「好き」または「嫌い」のマークを付けます。これが私のDBスキーマです。brewityのためにスキップされた重要でないフィールド:

  create_table "likes", :force => true do |t|
    t.integer  "oid"       # oid is photos.id
    t.integer  "user_id"   # user who liked this photo
    t.boolean  "mark",       :default => true
  end

  create_table "photos", :force => true do |t|
    t.string   "photo"   #filename of the photo
  end

  create_table "users", :force => true do |t|
    t.string   "firstname", 
    t.string   "lastname",  
    t.string   "email",   
  end

モデルは次のとおりです。

class Photo < ActiveRecord::Base    
  has_many  :likes,  :foreign_key => 'oid'
end

class Like < ActiveRecord::Base
  belongs_to :photo
end

class User < ActiveRecord::Base
  has_many  :likes, :through => :photos
end

1枚の写真に、1ユーザーにつき1つのマークが付きます。つまり、ユーザーは写真を 2 回以上「いいね」することはできません。

ユーザーが再ログインした後に、見積もりを出した写真を確認できるようにしたい。

今のところ、次のステートメントで写真を選択します: @photos = Photo.limit(30).offset(0) 次にテンプレートで: <%= photo.likes.where("user_id=#{current_user.id}") %>この後、30 以上の SQL クエリ、つまり N+1 問題が発生しました。

この問題を回避する 1 つのオプションは、写真を選択するときにいいね! を含めることです。

 @photos = Photo.includes(:likes ).limit(30).offset(0)

ただし、これにはすべてのユーザーからの写真に対するすべてのいいねが含まれ、アプリケーションのパフォーマンスに悪影響を及ぼします。さらに、現在のユーザーのレコードを抽出する必要があります。

2番目のオプションは、動的リレーションを作成することです

class User < ActiveRecord::Base
  has_many  :likes, :through => :photos, :conditions => "user_id = current_user.id"
end

このオプションでは、コントローラーからモデルに current_user.id を渡す必要がありますが、これは正しくないようです。

これを解決するのを手伝ってください

4

1 に答える 1

3

まず、これは設計上の問題です。これについて考えてみてください。「いいね」は、ユーザーと写真の間のある種の絆です。「写真は多くのユーザーに好かれているかもしれません。ユーザーは多くの写真を気に入っているかもしれません」

あなたのモデルがあなたのモデルとモデルLikeの間に立つべきであることは明らかではありませんか?PhotoUser

.----------.1   0..*.----------.0..*    1.----------.
|  users   |<-------|  likes   |-------->| photos   |
'----------'        '----------'         '----------'

class User < ActiveRecord::Base
  has_many :likes
  has_many :liked_photos, through: :likes, class: 'Photo'
end

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :photo
  # this will ensure that your users can only like a photo once.
  # you can also add a unique index to the two columns using 
  # add_index in a migration for more safety and performance.
  validates_uniqueness_of [:user, :photo]
end

class Photo < ActiveRecord::Base
  has_many :likes
  has_many :liking_users, through: :likes, class: 'User'
end

これで、関連する画像を効率的に取得するためにこれを行う必要があります。

@user   = User.includes( likes: :photos ).find( current_user.id )
@photos = @user.liked_photos
于 2011-11-07T20:16:47.047 に答える