envato/double_entry

AccountScopeMismatchError after an error

marcelo-soto opened this issue · 6 comments

Hi!,
I'm getting this error:

DoubleEntry::AccountScopeMismatchError (Expected instance of `User`, received instance of `User`)

every time I made an error in a method using DoubleEntry (even if the error is not DoubleEntry related). This happens in the console and the server, and the only solution is killing the server, restarting the console, and killing Spring.
I'm still using DoubleEntry in development, but I'm very afraid that the issue will cause a lot of trouble in production. Even using this #75 (comment) the issue remains.

Here's a more detailed example:
(everything works fine, on purpose delete a comma in a Hash)

SyntaxError (app/controllers/cartolas_controller.rb:16: syntax error, unexpected tIDENTIFIER, expecting ')'
...eEntry.account(:cilindros scope: x)}}
...                               ^
app/controllers/cartolas_controller.rb:23: syntax error, unexpected keyword_end, expecting '}'
app/controllers/cartolas_controller.rb:57: syntax error, unexpected keyword_end, expecting '}'):
  app/controllers/cartolas_controller.rb:16: syntax error, unexpected tIDENTIFIER, expecting ')'
  app/controllers/cartolas_controller.rb:23: syntax error, unexpected keyword_end, expecting '}'
  app/controllers/cartolas_controller.rb:57: syntax error, unexpected keyword_end, expecting '}'


  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_source.erb (5.4ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_trace.html.erb (2.5ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (1.3ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_web_console.html.erb (1.0ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (171.4ms)

Fixing the error, making the same request:

Started GET "/cartolas" for 127.0.0.1 at 2016-05-06 11:27:06 -0400
Processing by CartolasController#index as HTML
[...]
DoubleEntry::AccountScopeMismatchError (Expected instance of `User`, received instance of `User`):
  app/controllers/cartolas_controller.rb:13:in `block in index'
  app/controllers/cartolas_controller.rb:13:in `index'

Only restarting the servers everything is back to normal.

Please help me!!!

This same thing is happening to us. Would love to find a solution.

For us, any change in our development environment requires a restart of spring and/or the server, otherwise we get the DoubleEntry::AccountScopeMismatchError error.

Hi @doncote !, considering I posted this issue about 2 months ago and still don't have a formal solution, this is what I did:

in application_controller.rb

before_action :reload_accounts

...

  def reload_accounts
    DoubleEntry.configure do |config|
      config.accounts = nil
      config.transfers = nil
    end
    load "#{Rails.root.to_s}/config/initializers/double_entry.rb"
  end

I know it's ugly, slow and IDK if it's going to work in production, but I prefer that to restart the server.

I think we're going to fork the branch and pass strings instead of constants in the config and then constantize them when they're used. Will submit a pull req if we can nail it down.

Either that or we'll stop using Spring in dev/test. You should be okay in production since Spring isn't used there.

EDIT: removed issue code, as it was my own error.


General commen though: Is there a way we can rip out this nightmarish scoping magic and just keep the stable accounting parts we want?

It seems like all it should be doing is just-in-time account creation or finding upon being called. All these uses of delegate and active record scope chain add unnecessary complexity to something that seems like it could be setup to function totally namespaced and isolated from other activerecord models.

@marcelo-soto Is it possible this class level instance memoizing is causing the configuration to look stale?

E.g. this line from the double_entry gem:

  module Configurable
    def self.included(base) #:nodoc:
      base.extend(ClassMethods)
    end

    module ClassMethods #:nodoc:
      def configuration
        @configuration ||= self::Configuration.new
      end

      def configure
        yield(configuration)
      end
    end
  end

When the code comment for it was based on a Thoughtbot article that gave this example:

module Clearance
  class << self
    attr_accessor :configuration
  end

  def self.configure
    self.configuration ||= Configuration.new
    yield(configuration)
  end

  class Configuration
    attr_accessor :mailer_sender

    def initialize
      @mailer_sender = 'donotreply@example.com'
    end
  end
end

With self.configuration ||= Configuration.new being different from @configuration ||= self::Configuration.new ?! Unsure, but just a thought.

There are also thread safety issues to be careful about when using class level instance variables. Usually I imagine this doesn't matter as the instance variables don't change in value, but since double_entry uses them to construct account objects I'm less clear this can be assumed.

orien commented

Given the problems this active_record_scope_identifier method is causing, I propose to just delete it. In its place we can use a simple block:

user_scope = lambda do |user|
  raise 'account must be scoped by "User"' unless user.class.name == 'User'
  user.id
end
accounts.define(identifier: :savings,  scope_identifier: user_scope)