【问题标题】:Simulating has_many :through with Mongoid使用 Mongoid 模拟 has_many :through
【发布时间】:2011-09-13 00:38:01
【问题描述】:

我正在尝试创建一个使用 MongoDB 作为数据库的事件平台。我想要EventsUsers 之间的多对多关系。问题是,我希望关系中有属性(例如,Users 对于特定的Event 可以确认或未确认)。我意识到这将非常适合 RDBMS,但我使用 MongoDB 的原因是我正在其他地方利用它,我更愿意继续使用它。

我希望每个Event 嵌入许多属于UsersGuests。这样,我可以通过一个查询快速查看哪些用户正在参加活动。但是,我还想看看哪个EventsUser 正在快速参加,所以我希望每个User 都有一个Event 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 有一个 Guest 引用 uu 有一个引用 e

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

也许我走错了路。建议?谢谢。

【问题讨论】:

    标签: ruby-on-rails activerecord mongodb mongoid data-modeling


    【解决方案1】:

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

    当事件发生变化或用户因某种原因从事件中删除时,您必须管理数组。但这就是权衡。

    然后可以通过单个 db 调用找到 User.events。

    查看observers 管理关联。

    【讨论】:

    • 我刚看到你的回答。我发布了我最终如何解决我的问题,但使用观察者会更干净。谢谢!
    • 嘿,nodrog,链接坏了。
    【解决方案2】:

    我最终在模型中使用回调来完成我想要的。这是它的样子。

    编辑:我刚刚看到了 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
    

    【讨论】:

    • 有人能说出这样的最佳方法吗?
    • 我认为回调是有意义的。非常类似于观察者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2011-06-07
    相关资源
    最近更新 更多