3

今日の朝、モデルで定義されていない属性のレコードをmongoidが作成していたという奇妙な問題で目覚めました。

これを克服するために、Mongoid仕様でも言及されているattr_accessibleを実装することにしました

「フィールドのリストをアクセス可能として提供することは、単にそれらを保護することの逆です。アクセス可能として定義されていないものはすべてエラーを引き起こします。」--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

なぜこれがそうなのか、何か考えはありますか?

ありがとう

4

1 に答える 1

2

あなたの質問は有効です-以下のテストとMogoidコードの大まかな読みから、ドキュメントは一貫性がなく、完全に正しくなく、やや時代遅れになっているようです。

attr_protectedまたはattr_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
于 2012-05-08T16:17:45.873 に答える