Coder Social home page Coder Social logo

Comments (14)

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024 1

Thanks for the repo! I'm going to dig into this more and fix the issue on our side, but at the meantime you can fix the issue in a following way:

class Info
  def to_yaml
    @attributes.to_yaml
  end
end

The problem is that audited uses YAML to serialize object and later tries to restore Info as an object (while it's just a hash!), with this patch we will enforce Hash to be serialized.

from store_model.

taufek avatar taufek commented on May 23, 2024

Found a workaround by excluding the jsonb column from audited.

In example above I need to do

class Product < Application Record
  audited except: :info
  attribute :info, Info.to_type
end

from store_model.

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024

Interesting, could you please post the whole stack trace? And also the output of product.info.attributes.to_hash and product.attributes.to_hash

from store_model.

taufek avatar taufek commented on May 23, 2024

Spec:

RSpec.describe Product, type: :model do
  it 'creates Product' do
    product = Product.new
    product.info = { name: 'Dyson' }
    product.save

    expect(product).to be_persisted
  end
end

Output:

Failures:

  1) Product creates Product
     Failure/Error: product.save

     NoMethodError:
       undefined method `to_hash' for nil:NilClass
     # /usr/local/Cellar/tmuxinator/2.0.1/libexec/gems/audited-4.10.0/lib/audited/audit.rb:20:in `load'
     # /usr/local/Cellar/tmuxinator/2.0.1/libexec/gems/audited-4.10.0/lib/audited/auditor.rb:310:in `block in write_audit'
     # /usr/local/Cellar/tmuxinator/2.0.1/libexec/gems/audited-4.10.0/lib/audited/auditor.rb:309:in `write_audit'
     # /usr/local/Cellar/tmuxinator/2.0.1/libexec/gems/audited-4.10.0/lib/audited/auditor.rb:288:in `audit_create'
     # ./spec/models/product_spec.rb:7:in `block (2 levels) in <main>'

from store_model.

taufek avatar taufek commented on May 23, 2024
2.7.1 (main):0 > product = Product.new
=> #<Product:0x00007fe179ca97b8 id: nil, info: #<Info name: nil>, created_at: nil, updated_at: nil>
2.7.1 (main):0 > product.info.attributes
=> {"name"=>nil}
2.7.1 (main):0 > product.attributes.to_hash
=> {"id"=>nil, "info"=>#<Info name: nil>, "created_at"=>nil, "updated_at"=>nil}

from store_model.

taufek avatar taufek commented on May 23, 2024

I've created a temporary project to simulate above error. https://github.com/taufek/store_model_example

from store_model.

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024

@taufek here is a fix #86, could you please give it a shot before I merge it into the master?

from store_model.

taufek avatar taufek commented on May 23, 2024

I've updated store_model gem in my example repo to reference your PR branch and I'm still getting the same error.

taufek/store_model_example@7eab5db#diff-d09ea66f8227784ff4393d88a19836f321c915ae10031d16c93d67e6283ab55fR12

I've also tried the workaround above and also the same error.

from store_model.

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024

Oh, my bad, earlier I found out that something is wrong with YAML and made sure that Info is searialized properly. What I never made sure was that Product uses the fix to serialize itself. It does not 🤦‍♂️

I started to dig into how StoreModel is serialized and put some code to debug it. Turned out, that empty methods are enough to make specs pass:

class Info
  include StoreModel::Model

  attribute :name, :string

  def init_with(*)
    self
  end

  def encode_with(*); end
end

Could you please try it out?

By the way, audited also works fine when initialized in JSON mode.

from store_model.

taufek avatar taufek commented on May 23, 2024

It works! I can save the info in audits table (by audited gem).

Just one thing, I can't view the changes for Info in its original form. Here is the output from the audited_changes.

=2.7.1 (#<RSpec::ExampleGroups::Product::Create:0x00007fadbed65178>):0 > product.audits.first
=> #<Audited::Audit:0x00007fadbefb51a8
 id: 18,
 auditable_id: 60,
 auditable_type: "Product",
 associated_id: nil,
 associated_type: nil,
 user_id: nil,
 user_type: nil,
 username: nil,
 action: "create",
 audited_changes: {"info"=>#<Info:0x454c>},
 version: 1,
 comment: nil,
 remote_address: nil,
 request_uuid: "d9b8b07b-cb32-466b-a716-05b8932bc0ad",
 created_at: Sun, 07 Feb 2021 14:48:29.996951000 UTC +00:00>
2.7.1 (#<RSpec::ExampleGroups::Product::Create:0x00007fadbed65178>):0 > product.audits.first['info']
=> nil
2.7.1 (#<RSpec::ExampleGroups::Product::Create:0x00007fadbed65178>):0 > product.audits.first.audited_changes['info']
=> #<Info:0x4560>

I can't view the Info internal fields

from store_model.

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024

Looks like the problem is somewhere outside the gem 😕 I tried to remove StoreModel from your example and write everything using plain Attributes API:

class Info
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :name, :string
end


class Product < ApplicationRecord
  audited

  class InfoType < ActiveModel::Type::Value
    def cast_value(value)
      case value
      when String
        decoded = ActiveSupport::JSON.decode(value) rescue nil
        Info.new(decoded) unless decoded.nil?
      when Hash
        Info.new(value)
      when Info
        value
      end
    end

    def serialize(value)
      case value
      when Hash, Info
        ActiveSupport::JSON.encode(value)
      else
        super
      end
    end

    def changed_in_place?(raw_old_value, new_value)
      cast_value(raw_old_value) != new_value
    end
  end

  attribute :info, InfoType.new
end

Looks like audited breaks when object is serialized and then deserialized from YAML. Would you mind trying the above code in a branch and opening up an issue in audited repo? Maybe they can help us here

from store_model.

taufek avatar taufek commented on May 23, 2024

Ok. I will create an issue in audited repo. Thank you for your help.

from store_model.

DmitryTsepelev avatar DmitryTsepelev commented on May 23, 2024

Closing the issue for now, please let me know if you need any assistance

from store_model.

dminchev avatar dminchev commented on May 23, 2024

I will just add my solution here that seems to be quite easy to setup - audited_changes columns changes to jsonb and there it is.

collectiveidea/audited#567 (comment)

from store_model.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.