【问题标题】:How do you model "Likes" in rails?您如何在 Rails 中为“喜欢”建模?
【发布时间】:2012-08-14 03:43:03
【问题描述】:

我有 3 个模型:用户、对象、喜欢

目前,我有模型:一个用户有很多对象。我该如何进行建模:

1) 一个用户可以喜欢很多对象

2) 一个对象可以有很多赞(来自不同的用户)

所以我希望能够做这样的事情:

User.likes = 用户喜欢的对象列表

Objects.liked_by = 对象喜欢的用户列表

下面的模型肯定是错的……

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

class Likes < ActiveRecord::Base
  belongs_to :user
  belongs_to :object
end

class Objects < ActiveRecord::Base
  belongs_to :users
  has_many :users, :through => :likes    
end

【问题讨论】:

  • 你好像混淆了单复数
  • 是的,类名应该是LikeObject,而不是LikesObjects。不幸的是,你不能使用Object,因为它已经被Ruby 使用了。你必须想另一个名字。 Item 什么的。
  • 谢谢大家。我的模型现在都是单数的。此外,Object 类仅用于演示目的。我不知道你不能用任何一种方式命名它。感谢您的提示。

标签: ruby-on-rails ruby model


【解决方案1】:

为了进一步详细说明我对 Brandon Tilley 的回答的评论,我建议如下:

class User < ActiveRecord::Base
  # your original association
  has_many :things

  # the like associations
  has_many :likes
  has_many :liked_things, :through => :likes, :source => :thing
end

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :thing
end

class Thing < ActiveRecord::Base
  # your original association
  belongs_to :user

  # the like associations
  has_many :likes
  has_many :liking_users, :through => :likes, :source => :user
end

【讨论】:

  • 所以这行得通!将 has_many 名称更改为 like_things 和 likes_users 最终区分了 sql 的生成方式。我真的要感谢大家的帮助!
  • @severin 极简主义的Thing 桌子和极简主义的Like 桌子会是什么样子?
  • @pratski likes 表需要包含对用户和喜欢的东西的引用,所以它需要的绝对最少的东西是user_idthing_id。在things 表中你不需要什么特别的......
  • 这里绝对不需要连接模型。只需在 User 和 Thing 之间创建一个 HABTM 关系,在连接表中为每个“喜欢”创建一个新行,使用 @user.things 来查看他们喜欢的东西的数量和内容,反之亦然。如果需要,您还可以命名关联和表以遵循“like”命名。对于一个简单的事情恕我直言,代码太多了。
【解决方案2】:

你很近;要使用:through 关系,您首先必须设置您正在经历的关系:

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

class Likes < ActiveRecord::Base
  belongs_to :user
  belongs_to :object
end

class Objects < ActiveRecord::Base
  has_many :likes
  has_many :users, :through => :likes    
end

注意Objects应该has_many :likes,这样外键就在正确的位置。 (此外,您可能应该为您的模型使用单数形式 LikeObject。)

【讨论】:

  • 嗯,这并不完全有效。我想保留对象和用户之间的关联。一个对象属于一个用户,不管用户是否喜欢它。将其视为论坛帖子。帖子属于用户,即使他们不“喜欢”它。在这个模型中,我不能做这样的事情:User.objects 没有它来查看用户是否喜欢这个对象。
  • 然后只需添加这些关联:has_many :objects in Userbelongs_to :user in Objects。另一个建议:检查你的单数/复数用法:AR 类名应该总是单数。您需要为 Objects 找到另一个名称,因为单数会与 Object 基类发生冲突...
【解决方案3】:

这里有一个简单的方法来实现这一点。基本上,只要您使用 :class_name 选项指定正确的类名,您就可以根据需要创建任意数量的关系。但是,这并不总是一个好主意,因此请确保在任何给定请求期间只使用一个,以避免额外的查询。

class User < ActiveRecord::Base
  has_many :likes, :include => :obj
  has_many :objs
  has_many :liked, :through => :likes, :class_name => 'Obj'
end

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :obj
end

class Obj < ActiveRecord::Base
  belongs_to :user
  has_many :likes, :include => :user

  has_many :users, :through => :likes

  # having both belongs to and has many for users may be confusing 
  # so it's better to use a different name

  has_many :liked_by, :through => :likes, :class_name => 'User'   
end


u = User.find(1)
u.objs # all objects created by u
u.liked # all objects liked by u
u.likes # all likes    
u.likes.collect(&:obj) # all objects liked by u


o = Obj.find(1)
o.user # creator
o.users # users who liked o
o.liked_by # users who liked o. same as o.users
o.likes # all likes for o
o.likes.collect(&:user)

【讨论】:

  • 这不起作用,因为Object 是 Ruby 中的预定义类,是所有(或几乎所有 1.9)类的基类。
  • 当然不会。这只是为了说明基于问题的关系。改为对象。
【解决方案4】:

根据 Rails 建模的命名约定的模型和关联

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

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :object
end

class Object < ActiveRecord::Base
  belongs_to :user

  has_many :likes
  has_many :users, :through => :likes    
end

此外,您可以使用已经内置的 gem,例如 acts-as-taggable-on,无需代码即可拥有相同的功能 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    相关资源
    最近更新 更多