vendredi 11 décembre 2015

Class Methods Only Included Once When Using Concerns in Rails 3 with Namespaced Models

I have a folder structure that looks like the following:

app/models/
    concerns/
        quxable.rb
    foo/
        bar.rb
        baz.rb

I'm in Rails 3 so I've autoloaded my concerns with:

config.autoload_paths += Dir[Rails.root.join('app', 'models', "concerns", '**/')]

And the files are as follows:

quxable.rb

module quxable.rb
    extend ActiveSupport::Concern

    module ClassMethods
        def new_method
        end
    end
end

bar.rb

class Foo::Bar.rb < ActiveRecord::Base
    include Quxable
end

baz.rb

class Foo::Baz.rb < ActiveRecord::Base
    include Quxable
end

Now in the console if do this, I get the following outputs:

Foo::Bar.respond_to? :new_method #=> true
Foo::Baz.respond_to? :new_method #=> false
reload!
Foo::Baz.respond_to? :new_method #=> true
Foo::Bar.respond_to? :new_method #=> false

So it would seem to only be properly included on the model that is first accessed. And yet, If I run the following:

ActiveRecord::Base.descendants.select{ |c| c.included_modules.include?(Quxable) }.map(&:name)

I get ["Foo::Bar", "Foo::Baz"].

Any idea what's going on here? I'm guessing something with autoloading/eagerloading, but I'm not sure why both models aren't getting the new class method.

PS - I've tried rewriting the module without ActiveSupport::Concern (just because I'm on an old Rails version and I'm taking shots in the dark) using:

def include(base)
    base.send :extend, ClassMethods
end

but I still have the same problem.

Aucun commentaire:

Enregistrer un commentaire