使用 mongoid 进行嵌套质量分配

发布于 2024-11-03 15:39:37 字数 1284 浏览 1 评论 0原文

通过 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 更新查询...我在这里缺少什么?

with a has_one/belongs_to relationship, i cannot seem to update nested records via mass assignment.

models:

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

controller:

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

post request:

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

mongo query:

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

and i dont even get a mongo update query if the product_variation doesnt have any changed attributes... what am i missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘人皮目录ツ 2024-11-10 15:39:37

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

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

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

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

下一个问题是您需要将“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_variitation_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

Working models and a unit test are below to demonstrate that you can update child parameters and save to the database
through the parent as intended via accepts_nested_attributes_for and the autosave: true option for relations.

The Mongoid documentation says that an error will be raised for an attempt to set a protected field via mass assignment,
but this is out of date.
Instead, messages like the following are printed to the log file.

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

You should carefully look for for these messages in the appropriate log file to diagnose your problem.
This will help you notice that you have a nested id field for the shipping profile in your parameters,
and this seems to cause the weight to be rejected as well, probably along with all child parameters.
After adding "attr_accessible :id" to the ShippingProfile model, the weight now gets assigned.
You also need to add "attr_accessible :quantity" (and I've added :id for the unit test) to the ProductVariation model

The next issue is that you need "autosave: true" appended to the has_one relation
in order to have the child updated through the parent,
otherwise you will have to save the child manually.

You might also be interested in sanitize_for_mass_assignment, which can be used to launder out ids.

include ActiveModel::MassAssignmentSecurity

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

The unit test should make the whole subject clear, I'll leave the controller work to you.
Hope that this is clear and that it helps.

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

test output

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文