Mongoid attr_accessible无法正常工作

时间:2012-05-07 07:30:53

标签: mongodb mongoid attr-accessible

今天早上我醒来时有一个奇怪的问题,mongoid正在创建一个未在模型中定义的属性记录

为了克服这个问题,我决定实施attr_accessible,也提到Mongoid specification

  

“提供可访问的字段列表只是相反的   保护他们。 任何未定义为可访问的内容都会导致   错误。“ - Mongoid规范

认为一切都会正常工作我创建了一个虚拟记录,而且我很惊讶我插入了与上面的陈述相反的

  

任何未定义为可访问的内容都会导致错误

这是我的模型结构

class PartPriceRecord 
  include Mongoid::Document
    field :supplier_id,type: Integer
    field :part_number,type: String
    field :part_description, type: String
    field :core_indicator,type: String
    field :us_part_price,type: Float
    field :us_core_price,type: Float
    field :us_fleet_price,type: Float
    field :us_distributor_price,type: Float
    field :ca_part_price,type: Float
    field :ca_distributor_price,type: Float
    field :ca_core_price,type: Float
    field :ca_fleet_price,type: Float 
    field :basic_file_id,type: Integer
    index :part_number, unique: true

  validates_presence_of :supplier_id
  validates_presence_of :part_number
  #validates_uniqueness_of :part_number
  validates :part_number ,:format => { :with => /^[a-z0-9A-Z\s*-]+[-a-z0-9\s-]*[a-z0-9\s*-]+$/i ,:message => "Only AlphaNumeric Allowed" }
  validates :supplier_id, :format => { :with => /^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i , :message => "Only Alphanumeric Allowed" } 
  #validates :part_description,:presence => true

  validates :part_description,:format => { :with => /^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i ,:message => "Only Alphanumberic Allowed"} ,:allow_nil => true
  validates :core_indicator ,:inclusion => { :in => %w(Y N),
    :message => "%{value} is not a valid Coreindicator must be Y | N" 
   } ,:allow_nil => true,:allow_blank => true


 validates :us_part_price,:us_core_price,:us_fleet_price,:us_distributor_price,:ca_part_price,:ca_core_price,:ca_fleet_price,:ca_distributor_price ,:format => { :with => /^([0-9]+(\.([0-9]{2}|[0-9]{1}))?)$/ ,:message => "should look like money" } ,:allow_nil => true,:allow_blank => true

  @@required_attributes =[:supplier_id,:part_number,:part_description,:core_indicator,:us_part_price,:us_core_price,:us_fleet_price,:us_distributor_price,:ca_part_price,:ca_core_price,:ca_fleet_price,:ca_distributor_price]
  @@not_required_attributes = ["_id","basic_file_id"]  
  cattr_reader :required_attributes,:not_required_attributes
  attr_accessible :supplier_id,:part_number,:part_description, :core_indicator,:us_part_price,:us_core_price,:us_fleet_price,:us_distributor_price,:ca_part_price,:ca_distributor_price,:ca_core_price,:ca_fleet_price,:basic_file_id
end

这里是我从控制台创建的记录

ruby-1.9.2-head :003 > PartPriceRecord.count()
 => 260317 ## initial count before creating a new record
ruby-1.9.2-head :004 > p1 = PartPriceRecord.new(:customer_id => "One",:part_number => "ASA",:supplier_id => "Supp")
 => #<PartPriceRecord _id: 4fa77921d2d8d60e39000002, _type: nil, supplier_id: "Supp", part_number: "ASA", part_description: nil, core_indicator: nil, us_part_price: nil, us_core_price: nil, us_fleet_price: nil, us_distributor_price: nil, ca_part_price: nil, ca_distributor_price: nil, ca_core_price: nil, ca_fleet_price: nil, basic_file_id: nil> 
ruby-1.9.2-head :005 > p1.save
 => true  ## Record got created
ruby-1.9.2-head :006 > PartPriceRecord.count()
 => 260318  ## Count indicating record was created

知道为什么会这样吗?

谢谢

1 个答案:

答案 0 :(得分:2)

您的问题是有效的 - 从以下测试和粗略读取Mogoid代码看来,文档似乎不一致,不完全正确,有些过时。

attr_protected或NOT attr_accessible的字段忽略质量分配;他们不会在质量分配上引起错误。

在“受保护”一节中,“引发错误”不正确,文档甚至与用户和人员不匹配。在关于Accessible的部分中,“将导致错误”不正确,但注释“默默地忽略受保护的那些”给出了一个线索,即不会引发错误并且忽略质量分配。

这是来自mongoid / spec / mongoid / attributes_spec.rb的片段,支持此功能。

describe ".attr_accessible" do

  context "when the field is not _id" do

    let(:account) do
      Account.new(number: 999999)
    end

    it "prevents setting via mass assignment" do
      account.number.should be_nil
    end
  end
...
end

您必须将字段customer_id添加到PartPriceRecord模型中。我对User和PartPriceRecord的测试如下。希望这会有所帮助。

require 'test_helper'

class PartPriceRecordTest < ActiveSupport::TestCase
  def setup
    User.delete_all
    PartPriceRecord.delete_all
  end

  test "User" do
    assert_equal(0, User.count())
    # Set attributes on a user properly.
    user = User.new(first_name: "Corbin")
    assert_equal("Corbin", user.first_name)
    user.attributes = { first_name: "Corbin" }
    assert_equal("Corbin", user.first_name)
    user.write_attributes(first_name: "Corbin")
    assert_equal("Corbin", user.first_name)

    # Attempt to set attributes a user, raising an error. # <-- This documentation is incorrect, no error is raised
    #user = User.new(first_name: "Corbin", password: "password")
    user.attributes = { first_name: "Corbin", password: "password" } # inaccessible field is forced to nil
    assert_equal("Corbin", user.first_name)
    assert_equal(nil, user.password)
    user.write_attributes(first_name: "Corbin", password: "password") # inaccessible field is forced to nil
    assert_equal("Corbin", user.first_name)
    assert_equal(nil, user.password)
  end

  test "PartPriceRecord" do
    assert_equal(0, PartPriceRecord.count())
    p1 = PartPriceRecord.new(:customer_id => "One",:part_number => "ASA",:supplier_id => "Supp")
    assert_equal(nil, p1.customer_id)
    p1.save
    assert_equal(1, PartPriceRecord.count())
    assert_equal(nil, PartPriceRecord.find(p1.id).customer_id)
  end
end