使用Mongoid创建对象嵌入多对一关系

时间:2011-09-07 05:36:52

标签: ruby-on-rails-3 mongoid

我试图创建一个具有嵌入属性的对象进行测试。此示例使用具有多种语言的用户,但我希望能够为创建嵌入对象的一般情况提供解决方案。

展示创作代码:

def valid_attributes
  { :languages => [Language.new(language: "en-US", proficiency: "1")] }
end

user = User.create! valid_attributes

模特:

class User
  include Mongoid::Document
  field :languages
  embeds_many :languages 
  validates_presence_of :languages
  attr_accessible :languages_attributes
  accepts_nested_attributes_for :languages, :reject_if => lambda { |a| a[:language].blank? }, :allow_destroy => true
end

class Language
  include Mongoid::Document
  field :language
  field :proficiency
  key :language
  embedded_in :user
  attr_accessible :language, :proficiency 
end

这些模型适用于在Ryan Bates'中创建嵌套表单中的对象。脚步声(https://github.com/ryanb/complex-form-examples)。我不知道这是否正确,但我是这么认为的。

我可以看到一些明显的解决方案。一种是对输入进行硬编码,就像从表单生成的那样:

{"user"=>{ "languages_attributes"=>{"0"=>{"language"=>"en-US", "proficiency"=>"1", "_destroy"=>"false", "id"=>"en-dash-us"}}}

从长远来看,对我来说,这看起来并不干净。

另一个解决方案是剪切嵌入的对象并使用数组。 Mongoid非常擅长支持数组,但是你失去了为每个对象编写验证的能力,而且代码的可重用性也会降低。

想法,Stackoverflowers?

2 个答案:

答案 0 :(得分:3)

为了它的价值,我遵循@cug的建议并使用了Fabrication。我在这里发布我的代码是为了帮助其他人解决这个问题。

spec / user / fabricator.rb Fabricator

Fabricator(:language) do
  language "en-US"
  proficiency "1"
end

Fabricator(:user) do
  languages { [ Fabricate.build(:language, :language => "en-US", :proficiency => "1") ] } 
end

创建这样的用户:

user = Fabricate.build(:user)

谢谢大家,案件已经结案。 ^^

答案 1 :(得分:2)

你应该真的使用Fixtures,或者更好的工厂。 FactoryGirl很受欢迎  用于创建工厂。

在您的情况下,您必须在spec/factories.rb中定义工厂:

FactoryGirl.define do
  factory :user do
    languages { [association(:language)] }
  end

  factory :language do
    language "en-US"
    proficiency "1"
  end
end

而不是像你那样在你的测试中使用它

user = FactoryGirl.create :user