Mongoid Создать встроенный документ внутри родительского
У меня есть две модели User и Status. Статус встроен в пользователя:
User.rb
class User
include Mongoid::Document
include Mongoid::Timestamps
embeds_one :status, as: :statusable
Status.rb
class Status
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :statusable, polymorphic: true
Сейчас я пытаюсь создать статус Document Inside user:
* User.create!(:name =>'try',:status => {:num => '111'})
=> NameError: uninitialized constant Statu
from /var/lib/gems/1.9.1/gems/activesupport-3.2.13/lib/active_support/inflector/methods.rb:230:in 'block in constantize'
from /var/lib/gems/1.9.1/gems/activesupport-3.2.13/lib/active_support/inflector/methods.rb:229:in 'each'
....
....
* u = User.create!(:name =>'try')
u.status = Status.create!(:num => '222')
=> Mongoid::Errors::NoParent:
Problem:
Cannot persist embedded document Status without a parent document.
Summary:
If the document is embedded, in order to be persisted it must always have a reference to its parent document. This is most likely caused by either calling Status.create or Status.create! without setting the parent document as an attribute.
Resolution:
Ensure that you have set the parent relation if instantiating the embedded document direcly, or always create new embedded documents via the parent relation.
* u.status = {:num => '222'}
=> NameError: uninitialized constant Statu
Есть идеи, почему это происходит?
2 ответа
Из документации:
Название класса модели не может заканчиваться на "s", потому что оно будет рассматриваться как множественная форма слова. Например, Status будет рассматриваться как форма Statu во множественном числе, что вызовет несколько известных проблем.
Поэтому постарайтесь определить ваши отношения с class_name
метаданные заставляют mongoid использовать этот класс.
embeds_one :status, as: :statusable, class_name: "Status"
Здесь было несколько проблем. Как ответил Маркес, имя класса модели, оканчивающееся на "s", проблематично, но адресуется через спецификатор class_name. Если вам не нужен полиморфизм, то вы просто используете автоматически сгенерированные методы для User # status и User # status =. Но с полиморфизмом и переопределением class_name спецификатор "as:" у меня не сработал, а сработал следующий. Надеюсь, что это поможет вам двигаться дальше.
приложение / модели / user.rb
class User
include Mongoid::Document
include Mongoid::Timestamps
embeds_one :statusable, class_name: "Status"
end
приложение / модели / status.rb
class Status
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :statusable, polymorphic: true
end
Тест / блок / user_test.rb
require 'test_helper'
require 'pp'
class UserTest < ActiveSupport::TestCase
def setup
User.delete_all
end
test "basic embedding" do
User.create!(:name =>'try',:statusable => {:num => '111'})
assert_equal 1, User.count
u = User.create!(:name =>'try')
u.statusable = Status.new(:num => '222')
assert_equal 2, User.count
puts
pp (User.all.to_a.collect{|user| user.serializable_hash})
end
end
$ рейк тест
Run options:
# Running tests:
[1/1] UserTest#test_basic_embedding
[{"_id"=>"5277f5077f11bac4b4000001",
"created_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00,
"name"=>"try",
"statusable"=>
{"_id"=>"5277f5077f11bac4b4000002",
"created_at"=>nil,
"num"=>"111",
"updated_at"=>nil},
"updated_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00},
{"_id"=>"5277f5077f11bac4b4000003",
"created_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00,
"name"=>"try",
"statusable"=>
{"_id"=>"5277f5077f11bac4b4000004",
"created_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00,
"num"=>"222",
"updated_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00},
"updated_at"=>Mon, 04 Nov 2013 19:27:03 UTC +00:00}]
Finished tests in 0.044048s, 22.7025 tests/s, 45.4050 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips