简体   繁体   English

红宝石在轨,如何实现关系

[英]ruby on rails, how to implement relations

I'm stuck with this application ) I have 3 models - User, Photo and Like Users will log in, view photos and mark them "like" or "dislike". 我被这个应用程序卡住了)我有3种模型-用户,照片和喜欢用户将登录,查看照片并将它们标记为“喜欢”或“不喜欢”。 Here's my DB schema, insignificant fields skipped for 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

Here's models: 这是模型:

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

One photo will have one mark per user. 一张照片每位用户有一个标记。 ie user can't 'like' photo twice or more. 也就是说,用户不能“赞”照片两次或更多次。

I want users to be able to see which photos they have given estimates after they relogin. 我希望用户在重新登录后能够看到他们给出了哪些估算值的照片。

For now, I select photos with this statement: @photos = Photo.limit(30).offset(0) then in template: <%= photo.likes.where("user_id=#{current_user.id}") %> After this, I have 30+ SQL queries, or, in other words, N+1 problem. 现在,我用以下语句选择照片:@photos = Photo.limit(30).offset(0),然后在模板中:<%= photo.likes.where(“ user_id =#{current_user.id}”)%>在此之后,我有30多个SQL查询,或者换句话说,就是N + 1问题。

One option to avoid the problem is to include likes when selecting photos. 避免问题的一种选择是在选择照片时包含喜欢。

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

But this will include ALL likes for photo, from all users, and adversely affect the performance of application. 但这将包括所有用户对照片的所有喜欢,并且会对应用程序的性能产生不利影响。 Plus I'll have to extract record for current user. 另外,我必须提取当前用户的记录。

Second option is to create dynamic relation 第二种选择是创建动态关系

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

For this option, I'll have to pass current_user.id from controller to model, which doesn't look correct for me. 对于此选项,我必须将current_user.id从控制器传递到模型,这对我来说似乎不正确。

Please help to solve this 请帮忙解决这个问题

First of all, this is a design issue . 首先, 这是一个设计问题 Think about this : "like" is some kind of bond between a user and a photo. 考虑一下:“喜欢”是用户和照片之间的某种结合。 Just say it loud : "a photo may be liked by many users ; a user may like many photos". 只需大声说:“一张照片可能会被许多用户喜欢;一个用户可能会喜欢许多照片”。

Isn't it clear that your Like model should stand between your Photo and User model ? 不清楚您的“ Like模型应该位于“ Photo模型和“ User模型之间吗?

.----------.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

Now, you just have to do this to retrieve efficiently the relevant pictures: 现在,您只需执行此操作即可有效地检索相关图片:

@user   = User.includes( likes: :photos ).find( current_user.id )
@photos = @user.liked_photos

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM