【问题标题】:nested mass assignment with mongoid使用 mongoid 的嵌套质量分配
【发布时间】:2011-04-28 07:16:18
【问题描述】:

由于 has_one/belongs_to 关系,我似乎无法通过批量分配更新嵌套记录。

型号:

class ProductVariation
  include Mongoid::Document
  has_one                       :shipping_profile,  :inverse_of => :variation
  field                         :quantity
  attr_accessible               :shipping_profile_attributes
  accepts_nested_attributes_for :shipping_profile
end

class ShippingProfile
  include Mongoid::Document
  belongs_to       :variation, :class_name => "ProductVariation"
  field            :weight,    :type => Float
  attr_accessible  :weight
end

控制器:

@variation = ProductVariation.find(params[:id])
@variation.update_attributes(params[:product_variation])

发布请求:

Parameters:{
  "product_variation"=>{
    "quantity"=>"13",
    "shipping_profile_attributes"=>{
      "weight"=>"66",
      "id"=>"4dae758ce1607c1d18000074"
    }
  },
  "id"=>"4dae758ce1607c1d18000073"
}

mongo 查询:

MONGODB app_development['product_variations'].update({"_id"=>BSON::ObjectId('4dae758ce1607c1d18000073')}, {"$set"=>{"quantity"=>13, "updated_at"=>2011-04-28 06:59:17 UTC}})

如果 product_variation 没有任何更改的属性,我什至没有得到 mongo 更新查询...我在这里缺少什么?

【问题讨论】:

  • 您在哪个堆栈上运行?请指定 Ruby 实现、Rails 版本、Mongoid 版本和 ruby​​ 驱动版本。
  • ruby 1.9.2p180,rails 3.0.7,mongo 1.3.0,mongoid 2.0.1

标签: ruby-on-rails associations mongoid


【解决方案1】:

下面是工作模型和单元测试,以演示您可以更新子参数并保存到数据库 通过 accepts_nested_attributes_for 和关系的 autosave: true 选项按预期通过父级。

Mongoid 文档说尝试通过批量分配设置受保护的字段会引发错误, 但这已经过时了。 相反,类似以下的消息会打印到日志文件中。

WARNING: Can't mass-assign protected attributes: id

您应该在相应的日志文件中仔细查找这些消息以诊断您的问题。 这将帮助您注意到您的参数中有一个用于运输配置文件的嵌套 id 字段, 这似乎也导致权重被拒绝,可能与所有子参数一起被拒绝。 将“attr_accessible :id”添加到 ShippingProfile 模型后,现在会分配权重。 您还需要在 ProductVariation 模型中添加“attr_accessible :quantity”(我已经为单元测试添加了 :id)

下一个问题是您需要将“autosave: true”附加到 has_one 关系 为了让孩子通过父母更新, 否则您将不得不手动保存孩子。

您可能还对 sanitize_for_mass_assignment 感兴趣,它可用于清洗 id。

include ActiveModel::MassAssignmentSecurity

p sanitize_for_mass_assignment(params['product_variation'], :default)

单元测试应该使整个主题清晰,我将把控制器的工作留给你。 希望这很清楚并且对您有所帮助。

class ProductVariation
  include Mongoid::Document
  has_one                       :shipping_profile, :inverse_of => :variation, autosave: true
  field                         :quantity
  accepts_nested_attributes_for :shipping_profile
  attr_accessible               :id
  attr_accessible               :quantity
  attr_accessible               :shipping_profile_attributes
end

class ShippingProfile
  include Mongoid::Document
  belongs_to       :variation, :class_name => "ProductVariation"
  field            :weight,    :type => Float
  attr_accessible  :id
  attr_accessible  :weight
end

test/unit/product_varitation_test.rb

require 'test_helper'

class ProductVariationTest < ActiveSupport::TestCase
  def setup
    ProductVariation.delete_all
    ShippingProfile.delete_all
  end

  test "mass assignment" do
    params = {
      "product_variation"=>{
        "quantity"=>"13",
        "shipping_profile_attributes"=>{
          "weight"=>"66",
          "id"=>"4dae758ce1607c1d18000074"
        }
      },
      "id"=>"4dae758ce1607c1d18000073"
    }

    product_variation_id = params['id']
    shipping_profile_id = params['product_variation']['shipping_profile_attributes']['id']
    product_variation = ProductVariation.create("id" => product_variation_id)
    shipping_profile = ShippingProfile.create("id" => shipping_profile_id)
    product_variation.shipping_profile = shipping_profile
    assert_equal(1, ProductVariation.count)
    assert_equal(1, ShippingProfile.count)

    product_variation.update_attributes(params['product_variation'])
    assert_equal('13', ProductVariation.find(product_variation_id)['quantity'])
    assert_equal(66.0, ShippingProfile.find(shipping_profile_id)['weight'])
    p ProductVariation.find(product_variation_id)
    p ShippingProfile.find(shipping_profile_id)
  end
end

测试输出

Run options: --name=test_mass_assignment

# Running tests:

#<ProductVariation _id: 4dae758ce1607c1d18000073, _type: nil, quantity: "13">
#<ShippingProfile _id: 4dae758ce1607c1d18000074, _type: nil, variation_id: BSON::ObjectId('4dae758ce1607c1d18000073'), weight: 66.0>
.

Finished tests in 0.014682s, 68.1106 tests/s, 272.4424 assertions/s.

1 tests, 4 assertions, 0 failures, 0 errors, 0 skips

Process finished with exit code 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多