有人可以帮助我这个协会吗?

时间:2012-09-15 23:44:54

标签: ruby-on-rails associations

我正在尝试设置一个类似游戏的Rails应用程序。该应用程序具有用户,每个用户都可以创建Pawns。用户可以使用他们自己的一个Pawns搜索其他用户和他们创建的Pawns,并在他们喜欢的情况下挑战另一个用户。受挑战的用户可以接受/拒绝挑战。

现在我可以为用户添加/删除Pawns,我的模型看起来像这样:

class User < ActiveRecord::Base
  has_many :pawns, dependent: :destroy

class Pawn < ActiveRecord::Base
  belongs_to :user

现在,如果User1想要挑战User2创建的Pawn,他会查看User2的Pawn列表并点击他想要的Pawn的“Challenge”按钮。然后,User1必须选择他的一个Pawns用于挑战并点击保存。现在User2需要接受/拒绝挑战。

我很难理解应该如何设置挑战。我的想法是,每个Pawn都会有一个自我引用的多对多关系,几乎就像建立友谊关系一样。但是,我不知道是否应该考虑与用户或Pawn相关的挑战。

最好的方法是建模这样的东西吗?

修改

这是我想要完成的图表。我definitley认为我需要某种关联设置。结果将保存该挑战的Pawn统计数据(类似于time_spent,clicks_made等)。挑战也会有一个赢家或类似的专栏。

enter image description here

3 个答案:

答案 0 :(得分:3)

您的挑战可能会为每种类型的棋子定义关联。

class Challenge < ActiveRecord::Base
  # attributes :challengee_id, :challenger_id

  belongs_to :challengee, class_name: "Pawn"
  belongs_to :challenger, class_name: "Pawn"

  has_many :results
end

Pawns将针对每种类型的挑战建立关联。

class Pawn < ActiveRecord::Base
  # attributes :user_id

  belongs_to :user

  has_many :results
  has_many :initiated_challenges, class_name: "Challenge", foreign_key: :challenger_id
  has_many :received_challenges, class_name: "Challenge", foreign_key: :challengee_id
end

对于结果记录,可以对challenge_id进行非规范化。

class Result < ActiveRecord::Base
  # attributes: pawn_id, challenge_id, :result
  belongs_to :pawn
  belongs_to :challenge
end

您的用户可以通过棋子与棋子和挑战相关联。获得与用户相关联的两种挑战类型的简单方法是将两个挑战关联(发起和接收)的结果合并到一个方法#challenge中。

class User < ActiveRecord::Base
  has_many :pawns
  has_many :initiated_challenges, through: :pawns, source: :initiated_challenges
  has_many :received_challenges, through: :pawns, source: :received_challenges

  def challenges
    initiated_challenges + received_challenges
  end
end

此方法的性能优化可能包括将challenge_上的user_ids非规范化为challengee_user_id和:challenger_user_id ...或者在用户上缓存挑战ID列表,这样您就可以进行一次查询而不是两次查询。

答案 1 :(得分:2)

您可以设置另一个名为Challenges的表格,其中包含字段challenger_id, challengee_id, status。挑战者和挑战者ID当然代表了当然,而不是用户。状态代表challenge_pending, challenge_on_going,显然还有其他方法可以做到这一点,但是这一个。

这样做的另一个好处是,如果这是你想要的行为,你可以很容易地将pawn-pawn挑战限制为一个。

在视图控制器中

@challenges = Challenge.where("challengee_id IN (?)", Pawn.find_all_by_owner_id(current_user.id).map{|u| u[:id]})
@challenged = Challenge.where("challenger_id IN (?)", Pawn.find_all_by_owner_id(current_user.id).map{|u| u[:id]})

在你看来

<%= @challenges.each do |challenge| %>
  whatever
<% end %>

答案 2 :(得分:1)

class User < ActiveRecord::Base
    has_many :pawns
end

class Pawn < ActiveRecord::Base
    belongs_to :user

    has_many :challengers, class_name: 'Challenge'
    has_many :challengees, class_name: 'Challenge'

    belongs_to :result
end

class Challenge < ActiveRecord::Base
    belongs_to :challenger, class_name: 'Pawn'
    belongs_to :challengee, class_name: 'Pawn'

    belongs_to :result
end

class Result < ActiveRecord::Base
    has_one :challenge
    has_one :winner, class_name: 'Pawn'
end