Имитация has_many: через Mongoid - PullRequest
       32

Имитация has_many: через Mongoid

5 голосов
/ 13 сентября 2011

Я пытаюсь создать платформу событий, используя MongoDB в качестве базы данных.Я хочу отношения «многие ко многим» между Events и Users.Дело в том, что я хочу, чтобы в отношениях были свойства (например, Users может быть подтверждено или не подтверждено для конкретного Event).Я понимаю, что это идеально подходит для СУБД, но я использую MongoDB по причинам, которые я использую в других местах, и я предпочел бы продолжать использовать его.

Я хотел бы, чтобы каждый Event вставлял множество Guests, которые принадлежат Users.Таким образом, я могу видеть, какие пользователи посещают событие быстро и только с одним запросом.Тем не менее, я также хотел бы видеть, какие Events a User посещают быстро, поэтому я бы хотел, чтобы каждый User имел массив идентификаторов Event.

Вот сводка кода.

# 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 со ссылкой на u, а u имеет ссылку наe.

Я знаю, что строка has_many :through не будет работать.Какие-нибудь предложения относительно того, как получить подобную функциональность?Я думал об использовании обратного вызова after_create в Guest, чтобы добавить ссылку на Event в User, но это выглядит довольно глупо.

Может быть, я пошел по неверному пути.Предложения?Спасибо.

Ответы [ 2 ]

3 голосов
/ 19 сентября 2011

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

Редактировать: Я только что видел ответ Нодрога. Да, использование наблюдателей, вероятно, было бы лучше, я не знал о них. Спасибо!

# 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
3 голосов
/ 19 сентября 2011

Вы можете просто сохранить идентификаторы событий в массиве для пользователя.

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

User.events можно найти с помощью одного вызова db.

Посмотрите на наблюдателей , чтобы управлять ассоциацией.

...