liveh2o / active_remote

Active Remote provides Active Record-like object-relational mapping over RPC. It's Active Record for your platform.
MIT License
63 stars 23 forks source link

Getting `NoMethodError` when calling `super` in overridden association method #65

Closed minond closed 6 years ago

minond commented 6 years ago

I have a model with a has_many association and a custom reader method of the same name. I would expect that calling super would execute the original method, but it does not and I get a no such method exception instead. Removing everything from my model expect for the association and method, I am left with the following:

class Credential < ::ActiveRemote::Base
  has_many :credential_options

  def credential_options
    binding.pry
    @credential_options ||= super
  end
end

This is what I get when I run my code:

irb(main):001:0> Credential.new(:guid => "1").credential_options

From: /myapp/app/models/credential.rb @ line 5 Credential#credential_options:

    4: def credential_options
 => 5:   binding.pry
    6:   @credential_options ||= super
    7: end

[1] pry(#<Credential>)> defined? super
=> nil
[2] pry(#<Credential>)> exit
NoMethodError: super: no superclass method `credential_options' for #<Credential:0x482549c0>
Did you mean?  credential_options=
        from org/jruby/RubyBasicObject.java:1657:in `method_missing'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/activemodel-4.2.7.1/lib/active_model/attribute_methods.rb:430:in `method_missing'
        from /myapp/app/models/credential.rb:6:in `credential_options'
        from (irb):1:in `<eval>'
        from org/jruby/RubyKernel.java:1000:in `eval'
        from org/jruby/RubyKernel.java:1298:in `loop'
        from org/jruby/RubyKernel.java:1120:in `catch'
        from org/jruby/RubyKernel.java:1120:in `catch'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/railties-4.2.7.1/lib/rails/commands/console.rb:110:in `start'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/railties-4.2.7.1/lib/rails/commands/console.rb:9:in `start'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/railties-4.2.7.1/lib/rails/commands/commands_tasks.rb:68:in `console'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/railties-4.2.7.1/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from /home/.rbenv/versions/jruby-9.1.12.0/lib/ruby/gems/shared/gems/railties-4.2.7.1/lib/rails/commands.rb:17:in `<main>'
        from org/jruby/RubyKernel.java:961:in `require'
        from script/rails:6:in `<main>'
irb(main):002:0>

Commenting out the credential_options method allows the original method to work as expected:

irb(main):001:0> Credential.new(:guid => "1").credential_options
I, [2018-10-18T16:21:34.084808 #76011]  INFO -- : [CLT] - ...
=> []
irb(main):002:0>

Environment

$ ruby --version
jruby 9.1.12.0 (2.3.3) 2017-06-15 33c6439 Java HotSpot(TM) 64-Bit Server VM 25.171-b11 on 1.8.0_171-b11 +jit [darwin-x86_64]

$ cat Gemfile.lock
...
    active_remote (3.1.3)
      activemodel (>= 4.0, < 5)
      activesupport (>= 4.0)
      protobuf (>= 3.0)
    active_remote-bulk (0.1.0)
      active_remote (>= 2.4)
    active_remote-cached (0.1.4)
      active_remote
      activesupport
    active_remote-nullify (2.0.0)
      active_remote
    active_remote-pagination (2.3.0)
      active_remote (>= 2.1.0)
...
liveh2o commented 6 years ago

I can't believe I didn't think of this when we talked about it, but the problem is that the method being overridden is being redefined in the same class. Since it's not in a parent class, there is no parent method for super to invoke, hence the NoMethod error you are seeing. The workaround with alias you've been using is actually the correct way to do this (assuming overriding an association is actually what you want to do).

An alternative would be simply not to define association at all.

minond commented 6 years ago

Makes sense.