embeds_many и embeds_one из той же модели с Mongoid - PullRequest
6 голосов
/ 16 октября 2011

У меня есть две модели: блог и тема. Блог embeds_many: themes и Theme embedded_in: blog. У меня также есть блог embeds_one: theme (для активированной темы). Это не работает. При создании темы с blog.themes.create она не сохраняется. Если я изменю коллекции, чтобы они не были встроены, все работает.

# This does NOT work!
class Blog
  embeds_many :themes
  embeds_one  :theme
end

class Theme
  embedded_in :blog
end

НО

# This DOES work!
class Blog
  has_many :themes
  has_one  :theme
end

class Theme
  belongs_to :blog
end

Кто-нибудь знает, почему это так?

UPDATE

Также существует проблема с назначением одной из тем (выбранной) теме.

blog.themes = [theme_1, theme_2]
blog.save!

blog.theme = blog.themes.first
blog.save!

blog.reload
blog.theme # returns nil

Ответы [ 3 ]

2 голосов
/ 12 января 2015

При таком подходе вы будете встраивать один и тот же документ дважды: один раз в коллекцию тем, а затем в выбранную тему.

Я бы порекомендовал удалить второе отношение и использовать строковый атрибут для хранения текущегоназвание темыВы можете сделать что-то вроде:

class Blog
  include Mongoid::Document
  field :current_theme_name, type: String

  embeds_many :themes

  def current_theme
    themes.find_by(name: current_theme_name)
  end
end

class Theme
  include Mongoid::Document
  field :name, type: String

  embedded_in :blog
end

Обратите внимание, что вложенные документы mongoid инициализируются одновременно с основным документом и не требуют дополнительных запросов.

1 голос
/ 16 января 2015

Удалите embeds_one :theme и вместо этого поместите его методы получения и установки в класс Blog:

def theme
  themes.where(active: true).first
end

def theme=(thm)
  theme.set(active: false)
  thm.set(active: true)
end

Нет необходимости вызывать blog.save! после blog.theme = blog.themes.first, потому что set выполняет атомарную операцию.

Кроме того, не забудьте добавить field :active, type: Boolean, default: false в вашу Theme модель.

Надеюсь, это работает с вами.

1 голос
/ 18 ноября 2011

ОК, поэтому у меня возникла та же проблема, и я только что наткнулся на решение (я проверял код для метаданных по отношениям ).

Попробуйте это:

class Blog
  embeds_many :themes, :as => :themes_collection, :class_name => "Theme"
  embeds_one  :theme, :as => :theme_item, :class_name => "Theme"
end

class Theme
  embedded_in :themes_collection,     :polymorphic => true
  embedded_in :theme_item,     :polymorphic => true
end

Что я обнаружил предположил, что:

  • первый параметр (например, :themes) фактически становится именем метода.
  • :as подделывает фактические отношения, поэтому необходимость их сопоставления в обоих классах.
  • :class_name кажется довольно очевидной, класс, используемый для фактической сериализации данных.

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

...