Помогите понять полимофические ассоциации (рельсы) - PullRequest
3 голосов
/ 06 сентября 2010

Я знаю, что на это есть много ресурсов, но мне трудно связать любой из них с моей ситуацией, поэтому я надеялся, что кто-нибудь сможет помочь мне прояснить, как это работает:

В основном у меня есть модель Action (которая создается каждый раз, когда пользователь делает что-то, что влияет на другого пользователя, например, комментируя его статью или голосуя за чью-то фотографию), эти действия будут перечислены на панели пользователя. страница как все действия, которые имеют к ним отношение, как поток ... вроде как "лента новостей" Github

Github's

Я решил заняться созданием полиморфной ассоциации, вот как выглядит моя модель:

class Action < ActiveRecord::Base
  belongs_to :instigator, :polymorphic => true
  belongs_to :victim, :polymorphic => true
end

Я использовал зачинщика и жертву, потому что каждый может создать эти действия, которые в свою очередь всегда влияют на другого пользователя, вот моя User модель

class User < ActiveRecord::Base
  has_many :actions, :as => :instigator
  has_many :actions, :as => :victim
end

И именно здесь Я думаю Я иду не так, потому что в конечном итоге я хочу получить запрос, который, когда я запускаю что-то вроде User.find(1).actions, фактически возвращает все экземпляры, в которых пользователь одновременно instigator или victim, я думаю, что у меня не может быть обоих этих have_many, потому что при таком использовании я получаю только те случаи, когда пользователь является victim.

Вот моя миграция:

create_table :actions do |t|
  t.references :instigator, :polymorphic => true
  t.references :victim, :polymorphic => true
  t.string :action_performed
  t.references :resource, :polymorphic => true
  t.timestamps
end

Спасибо за любую помощь, мне всегда нравятся отличные предложения и помощь, которую предоставляет SO-сообщество.

Ответы [ 2 ]

2 голосов
/ 06 сентября 2010

Это напоминает классическую модель проблемы Дружбы.Полиморфная ассоциация не имеет значения.

Независимое от Rails решение:

class User < ActiveRecord::Base
  has_many :instigator_actions, :class_name => "Action", :as => :instigator
  has_many :victim_actions, :class_name => "Action", :as => :victim
  has_many :actions, :finder_sql => '
       SELECT a.* 
       FROM   actions a
       WHERE  (a.instigator_type = "User" AND instigator_id = #{id}) OR 
              (a.victim_type     = "User" AND victim_id     = #{id})'
end

При создании действий создайте их, используя одну из первых двух ассоциаций.

u1.instigator_actions.create(:victim => u2)

ИЛИ

u1.victim_actions.create(:instigator => u2)

В то же время вы можете получить список действий, связанных с пользователем, используя ассоциацию actions.

u1.actions
1 голос
/ 06 сентября 2010

Во-первых, я предлагаю вам использовать роли через наследование одной таблицы. В вашей пользовательской таблице вы можете иметь столбец типа, который идентифицирует кого-то как зачинщика или как жертву. (Конечно, если кто-то и тот и другой, у него будет 2 строки, поэтому вам нужно убедиться, что у вас нет имени в качестве первичного ключа.)

Так что теперь у вас есть более структурированный макет. Переходя к проблеме полиморфизма, попробуйте использовать другой интерфейс. Как в,

class Action < ActiveRecord::Base
  belongs_to :actionable, :polymorphic => true
end

actionable не обязательно должен быть отдельным классом. Это просто имя, данное интерфейсу. Как и на другой стороне ассоциации.

The Rails Way Оби Фернандеса (Obie Fernandez) дает вам четкое представление об этом, поэтому вы можете обратиться к нему для получения дополнительной информации о полиморфных ассоциациях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...