Как вы моделируете "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, чтобы иметь одинаковую функциональность без кода:)