Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-5404

Populate attributes_before_type_cast on read from database

    • Type: Icon: Improvement Improvement
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 8.0.1
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Minor Change

      attributes_before_type_cast is used by ActiveRecord to store incoming values when type conversions are performed during attribute assignment and when reading data from the database (where no type conversion normally happens, thus attributes_before_type_cast is the same as attributes). The equivalent operations in Mongoid are mongoization and demongoization. Currently Mongoid only populates attributes_before_type_cast during attribute assignment (prior to mongoization). Mongoid should also populate attributes_before_type_cast during demongoization, as part of instantiating models during reads from thedatabase.

      The new behavior will match AR. Currently, since attributes_before_type_cast are always empty on a model just retrieved from the database, users shouldn't be using this method for anything as it essentially doesn't work. Making it work as per AR is not expected to cause compatibility issues.

      The contents of attributes_before_type_cast can be one of two totally different types: user input upon assignment, raw DB data upon read from DB. In case of Mongoid this is pre-mongoized and pre-demongoized input which could be of totally different types (e.g. Range & Hash). For AR, the behavior is actually the same for hstore for example:

      class CreateTypeTests < ActiveRecord::Migration[7.0]
        def change
          create_table :type_tests do |t|
            t.string :str
            t.decimal :dec
            t.time :t
            t.timestamp :ts
            t.hstore :hs
            t.text :a, array: true
            t.inet :i
      
            t.timestamps
          end
        end
      end
      
      
      irb(main):004:0> a=TypeTest.new(hs:{a:42})
      => 
      #<TypeTest:0x00007f6cc29d1238
      ...
      irb(main):005:0> a.attributes_before_type_cast
      => 
      {"id"=>nil,
       "str"=>nil,
       "dec"=>nil,
       "t"=>nil,
       "ts"=>nil,
       "hs"=>{:a=>42},
       "a"=>nil,
       "i"=>nil,
       "created_at"=>nil,
       "updated_at"=>nil}
      irb(main):006:0> a.save!
        TRANSACTION (0.4ms)  BEGIN
        TypeTest Create (0.7ms)  INSERT INTO "type_tests" ("str", "dec", "t", "ts", "hs", "a", "i", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"  [["str", nil], ["dec", nil], ["t", nil], ["ts", nil], ["hs", "\"a\"=>\"42\""], ["a", nil], ["i", nil], ["created_at", "2022-07-01 15:53:22.582224"], ["updated_at", "2022-07-01 15:53:22.582224"]]
        TRANSACTION (6.0ms)  COMMIT
      => true
      irb(main):007:0> a.attributes_before_type_cast
      => 
      {"id"=>45,
       "str"=>nil,
       "dec"=>nil,
       "t"=>nil,
       "ts"=>nil,
       "hs"=>"\"a\"=>\"42\"",
       "a"=>nil,
       "i"=>nil,
       "created_at"=>Fri, 01 Jul 2022 15:53:22.582224000 UTC +00:00,
       "updated_at"=>Fri, 01 Jul 2022 15:53:22.582224000 UTC +00:00}
      
      

      assigning a value to an attribute writes the original input into ABTC
      saving the model resets ABTC to mongonized attribute values (as they are written into DB)
      reloading a model resets ABTC to mongoized attribute values as they are in DB
      reading a model from DB writes attribute values as they are in DB to ABTC

      Tests:

      Test *_before_type_cast followed by attributes_before_type_cast, attributes_before_type_cast should have all attributes in the model

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: