使用Mongoid模拟has_many :through关系

5
我正在尝试使用MongoDB作为数据库创建事件平台。我希望在“事件”和“用户”之间建立多对多的关系。但是,我想在关系中添加属性(例如,“用户”可以针对特定的“事件”确认或未确认)。我意识到这可能更适合关系型数据库,但是由于我在其他方面正在利用MongoDB,因此我宁愿继续使用它。
我希望每个“事件”都嵌入许多属于“用户”的“来宾”。这样,我就可以通过一次查询快速查看哪些用户参加了某个事件。但是,我还想快速查看哪些“事件”一个“用户”参加,因此我希望每个“用户”都有一个“事件”id数组。
以下是代码概述。
# user of the application
class User
  has_many :events
end

# event that users can choose to attend
class Event
  embeds_many :guests
  has_many :users, :through => :guests      # Won't work
end

# guests for an event
class Guest
  field :confirmed?, type: Boolean

  embedded_in :event
  belongs_to  :user
end


# Ideal use pattern
u = User.create
e = Event.create
e.guests.create(:user => u, :confirmed => true)

在理想的使用模式下,e具有对u的引用和u具有对e的引用。

我知道has_many: through这一行不起作用。如何获得类似的功能?我考虑在Guest中使用after_create回调来添加对User中的Event的引用,但这似乎很hacky。

也许我走了错误的路。有什么建议吗?谢谢。

2个回答

3

你可以将事件ID存储在用户的数组中。

当事件发生变化或是用户因某些原因被移除时,需要管理该数组。但这是权衡取舍。

通过单个数据库调用就可以找到用户参与的所有事件。

查看观察器以管理关联关系。


我刚刚看到了你的回答。我已经发布了我是如何解决我的问题的,但使用观察者可能会更加简洁。谢谢! - cbrauchli
嘿,nodrog,链接已经失效了。 - Fernando Kosh

3

我最终在模型中使用回调函数来实现我想要的功能。以下是代码示例。

编辑:我刚看到nodrog的答案。是的,使用观察者可能会更整洁,我之前不知道它们。谢谢!

# user of the application
class User
  has_and_belongs_to_many :events, inverse_of: nil, dependent: :nullify
end

# event that users can choose to attend
class Event
  embeds_many :guests
  index 'guests.user_id', unique: true
  before_destroy :cleanup_guest_references

  def cleanup_guest_references
    self.guests.each do |guest|
      guest.destroy
    end
  end
end

# guests for an event
class Guest
  field :confirmed?, type: Boolean

  embedded_in :event, :inverse_of => :guests
  belongs_to  :user

  after_create :add_event_for_user
  before_destroy :remove_event_for_user

  private
    def add_event_for_user
      self.user.events.push(self.event)
    end
    def remove_event_for_user
      self.user.events.delete self.event
      self.user.save
    end
end

有人能说一下做这样事情的最佳方式吗? - Fernando Kosh
我认为回调函数很有道理。与观察者非常相似。 - kgpdeveloper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接