Как вы моделируете "Likes" в рельсах?

У меня есть 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

Ответ 1

Чтобы подробнее рассказать о моем комментарии к Брэндону Тилли, я бы предложил следующее:

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

Ответ 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, так что внешний ключ находится в нужном месте. (Кроме того, вы, вероятно, должны использовать для своих моделей единую форму Like и 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 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)

Ответ 4

Модели и ассоциации в соответствии с соглашениями об именах моделирования рельсов

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

Кроме того, вы можете использовать уже встроенные драгоценные камни, такие как acts-as-taggable-on, чтобы иметь одинаковую функциональность без кода:)