Как настроить и работать с RoR Complex Joins? - PullRequest
0 голосов
/ 31 марта 2009

Этот код взят из предыдущего вопроса, но мой вопрос имеет к нему непосредственное отношение, поэтому я скопировал его здесь:

class User < ActiveRecord::Base
  has_many :group_memberships
  has_many :groups, :through => :group_memberships
end

class GroupMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
  belongs_to :group
end

class Role < ActiveRecord::Base
  has_many :group_memberships
end

class Group < ActiveRecord::Base
  has_many :group_memberships
  has_many :users, :through > :group_memberships
end

Новый вопрос ниже

Как вы можете продвинуть приведенный выше код на один шаг вперед и добавить и работать с друзьями?

class User < ActiveRecord::Base
  has_many :group_memberships
  has_many :groups, :through => :group_memberships
  has_many :friends # what comes here?
  has_many :actions
end

В коде выше я также добавил действия. Допустим, система отслеживала действия каждого пользователя на сайте. Как бы вы запрограммировали это так, чтобы каждое действие было уникальным и сортировалось с самым последним наверху для всех друзей пользователя?

<% for action in @user.friends.actions %>
 <%= action.whatever %>
<% end %>

Код выше может быть недействительным, вы можете сделать что-то вроде того, что у меня ниже, но тогда действия не будут отсортированы.

<% for friend in @user.friends %>
 <% for action in friend.actions %>
  <%= action.whatever %>
 <% end %>
<% end %>

UPDATE

Полагаю, реальная проблема здесь в том, как определить друзей? Создать новую модель или объединить таблицу, которая связывает пользователей с другими пользователями? В идеале я хотел бы определить друзей через общее членство в группах других пользователей, но я не уверен, как это определить.

has_many :friends, :through => :group_memberships, :source => :user

Но это не работает. Какие-нибудь идеи или предложения по передовому опыту?

Ответы [ 3 ]

0 голосов
/ 31 марта 2009

Чтобы добавить друзей, вы можете использовать has_and_belongs_to_many или has_many: through. Здесь - пример того, как это сделать. Вы должны самостоятельно присоединиться к таблице пользователей.

Чтобы просмотреть последние действия, получите их из базы данных, используя: order =>: made_at (или: updated_at) Чем вы можете отфильтровать действия, которые не принадлежат пользователям.

@actions = Action.all(:order => :created_at).select {|a| a.user.friends.include?(@user)}

Возможно, вы также можете написать SQL-запрос для этого.

0 голосов
/ 01 апреля 2009

Вы можете создать «друг» объект, который использует таблицу «user» и перейти оттуда, или вы могли бы определите друга как частичную сущность (имя друга и ссылка на user_id) и перетащите объект пользователя в объект друга.

Мне больше нравится эта последняя модель, потому что она позволяет вам легче представлять "удаленных" друзей. У вас все равно будет копия имени друга (даже если оно является дубликатом имени пользователя) и идентификатор, чтобы определить, ушел пользователь или нет. Сохраняет концепцию «друга» чуть дальше от концепции «пользователя» и любых последствий для безопасности. Я буду утверждать, что целесообразно отменить нормализацию для дублирования поля «имя», поскольку оно добавляет гибкость и «теневую» информацию о пользователе, который раньше существовал.

Хотя я так понимаю. Вам все равно придется со временем самостоятельно вернуться к пользовательской таблице, но, возможно, не так сильно. Если вы ДЕЙСТВИТЕЛЬНО не любите отменять нормализацию чего-либо, у вас может быть объект Person, к которому Друг и Пользователь обращаются за информацией. Лично я думаю, что это хорошая теоретическая конструкция, но не стоит той сложности, которую она привнесет в основную часть вашего кода (80% из них говорят о пользователе, а 20% говорят о друге). Я бы хотел, чтобы с пользователем было легко говорить, а с другом - немного сложнее ... не то и другое. :)

Надеюсь, это поможет. Мне нравилось мысленно играть с этим. :)

0 голосов
/ 31 марта 2009

Прошло много времени с тех пор, как я работал с Rails (вспомним Rails 1.x), но я думаю, вы можете сделать что-то вроде следующего:

Action.find(:all, :conditions => ['user_id in (?)', @user.friends.map(&:id)], :order => 'actions.date DESC')

, а затем, по вашему мнению:

<% @actions.each do |action| %>
  <%= action.whatever -%>
<% end %>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...