vigetlabs / active_admin_associations

This extends ActiveAdmin to allow for better editing of associations.
MIT License
119 stars 55 forks source link

NoMethodError: Protected method 'default_input_type' in ruby 2.1.0p0 #15

Closed scarfacedeb closed 10 years ago

scarfacedeb commented 10 years ago

I'm getting NoMethodError in Admin/companies#new in ruby 2.1.0p0. (RVM) In particular: protected method 'default_input_type' called for #<ActiveAdmin::FormBuilder:0x00000008f20488>

Backtrace

This error is coming from f.inputs/f.input methods inside my model configurations. The most interesting part of the Full trace:

# I've got f.input :title on app/admin/review_companies.rb:13 line

formtastic (2.2.1) lib/formtastic/helpers/input_helper.rb:236:in `input'
activeadmin (0.6.2) lib/active_admin/form_builder.rb:19:in `block in input'
activeadmin (0.6.2) lib/active_admin/form_builder.rb:177:in `with_new_form_buffer'
activeadmin (0.6.2) lib/active_admin/form_builder.rb:19:in `input'
app/admin/review_companies.rb:13:in `block (2 levels) in <top (required)>'

Surprisingly, it works fine with ruby 2.0.0p353. I have no idea why.

Gem versions: aa_associations (0.1.2) from RubyGems activeadmin (0.6.2) formtastic (2.2.1)

OS: Debian Linux 3.10-3-amd64

Related issue in activeadmin repo: https://github.com/gregbell/active_admin/issues/2863#issuecomment-32196887

Possible cause

I'm not sure, but I think that the whole problem lies in Formtastic::TokenInputDefaultForAssociation module (_/lib/formtastic/token_input_default_forassociation.rb) that aliases default_input_type. And that module is dynamically included in Formtastic::Helpers::Input (_lib/active_adminassociations/engine.rb:19).

As a result, formtastic tries to call that aliased default_input_type_with_token_default_for_association method, which is placed inside another module. and it causes ruby to throw an exception.


Also, I managed to recreate that error using that code:

require 'active_support/all'

module Module1
  extend ActiveSupport::Concern

  included do
    alias_method_chain :default_input_type, :test
  end

  def default_input_type_with_test
    puts 'module 1 - aliased'

    default_input_type_without_test
  end
end

module Module2
  protected

  def default_input_type
    puts "module2 !"
  end
end

class Klass1
  include Module2
end

x = Klass1.new
x.default_input_type # == "module2 !"
puts

Module2.send(:include, Module1)

y = Klass1.new
y.default_input_type # ==  protected method `default_input_type' called for #<Klass1:0x000000029caf70> (NoMethodError)
skull-squadron commented 10 years ago

@scarfacedeb Thanks for doing the isolation legwork.

The simplest hack for now is forking Formtastic with default_input_type made public. The only claim on this is that it stops the crashing. No warranties, no refunds. :)

gem 'formtastic', github: 'steakknife/formtastic'

davisinfo commented 10 years ago

Active admin form builder is using inherited method input which calls protected method default_input_type but since ActiveAdmin::FormBuilder is not the same class as Formtastic::FormBuilder it doesn't work. You can change the visibility of default_input_type by adding the following code to an initialiser

class ::Formtastic::FormBuilder public :default_input_type end

and the error will disappear.

brianjlandau commented 10 years ago

Given the advice above and a passing build for Ruby 2.1.0 and Ruby 2.0.0 on Travis I'm marking this as closed.