如何设置和使用RoR Complex Joins?

时间:2009-03-31 18:56:01

标签: ruby-on-rails ruby

此代码取自上一个问题,但我的问题直接与之相关,所以我在这里复制了它:

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 %>

更新

我想这里真正的问题是如何定义朋友?我是否创建了一个将用户链接到其他用户的新模型或连接表?理想情况下,我想通过其他用户的公共组成员资格来定义朋友,但我不确定如何定义它。

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

但这不起作用。任何想法或最佳实践建议?

3 个答案:

答案 0 :(得分:0)

我使用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 %>

答案 1 :(得分:0)

要添加朋友,您可以使用has_and_belongs_to_many或has_many:through。 Here是如何做到的示例。你应该自己加入用户表。

要列出最近的操作,请使用以下命令从db获取:order =&gt; :created_at(或:updated_at)。您可以过滤掉不属于用户的操作。

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

也许您也可以编写SQL查询来执行此操作。

答案 2 :(得分:0)

你可以创建一个使用“用户”表的“朋友”对象,然后从那里开始,或者你可以 将朋友定义为部分实体(朋友姓名和user_id引用),并将用户对象拉入朋友对象。

我更喜欢这个最后一个模型,因为它可以让你更容易地代表“已删除”的朋友。您仍然可以获得朋友姓名的副本(即使它是用户名的副本)以及用于标识用户是否已离开的ID。保持“朋友”概念远离“用户”概念和任何安全隐患。我认为复制“名称”字段是合适的去规范化,因为它增加了关于曾经存在的用户的灵活性和“影子”信息。

我接受了它。您仍然必须最终自我加入回用户表,但可能没有那么多。如果你真的讨厌去规范化任何东西,你可以拥有一个朋友和用户都参考的Person对象来获取信息。就我个人而言,我认为这是一个很好的理论构造,但不值得将其引入大部分代码的复杂性(其中80%是谈论用户而20%是谈论朋友)。我会让用户容易谈论和朋友有点难......不是两者兼而有之。 :)

希望这会有所帮助。我喜欢这个人的精神上玩弄。 :)