I am trying to extract some code I have written into a plugin (an engine actually, since I want to share the views to new apps). I really like the organization I see in the new Clearance engine - esp with respect to how they organize testing of the engine + testing the integration of the engine into your app (http:// giantrobots.thoughtbot.com/2009/4/22/clearance-is-a-rails-engine). So I have been following their method of creating modules and then including those modules into models so that things are well set up for overriding in the enclosing app. This was going well for the first couple models - and then I tried to convert my photo model that depends on attachment_fu. module Experts module Photo def self.included(model) # model.send(:include, ClassMethods) model.send(:include, Callbacks) model.send(:include, Relationships) model.send(:include, Validations) end module CallBacks has_attachment :storage => :file_system, :path_prefix => ''public/ photos'', :content_type => :image, :min_size => 1.kilobyte, :max_size => 3.megabyte, :thumbnails => {:thumbnail => ''x100>''} end ... end end The server will not start. Initially this complained vendor/plugins/experts/lib/experts/photo.rb:15: undefined method `has_attachment'' for Experts::Photo::CallBacks:Module (NoMethodError) So I changed the file that is called when my experts plugin is initialized to include methods from the attachment_fu plugin. require ''technoweenie/attachment_fu'' include Technoweenie::AttachmentFu::ActMethods This changed the error to: vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb:180:in `extended'': undefined method `class_inheritable_accessor'' for Experts::Photo::CallBacks:Module (NoMethodError) Following this back, class_inheritable_accessor is a Rails extension to Class from activesupport/lib/active_support/core_ext/class/ inheritable_attributes.rb I am a little stumped at how to make sure those methods are available when my plugin is loaded. Attachment_fu loads just fine without explicitly requiring active_support (though I do see that the CoreImage stuff in its vendor directory does have a "require ''active_support''" line.) But I tried adding that to my initialization file just to see; it did not help. The default plugin load order says it is alphabetical, so attachment_fu should be loaded before experts. Specifying the load order using config.plugins in the enclosing app does not help. The bottom line is I don''t understand plugin loading. Can someone give me some pointers? The part I find most puzzling is why attachment_fu loads when used in an app but my plugin that depends on it can''t.
Frederick Cheung
2009-Jul-30 20:57 UTC
Re: Problem loading plugin that depends on another plugin
On Jul 30, 4:21 pm, cnk <cynthia.ki...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> module Experts > module Photo > > def self.included(model) > # model.send(:include, > ClassMethods) > model.send(:include, Callbacks) > model.send(:include, Relationships) > model.send(:include, Validations) > end > > module CallBacks > has_attachment :storage => :file_system, :path_prefix => ''public/ > photos'', > :content_type => :image, > :min_size => 1.kilobyte, :max_size => 3.megabyte, > :thumbnails => {:thumbnail => ''x100>''} > end > ... > end > end > > The server will not start. Initially this complained > > vendor/plugins/experts/lib/experts/photo.rb:15: undefined method > `has_attachment'' for Experts::Photo::CallBacks:Module (NoMethodError) > > So I changed the file that is called when my experts plugin is > initialized to include methods from the attachment_fu plugin. >> The bottom line is I don''t understand plugin loading. Can someone give > me some pointers? The part I find most puzzling is why attachment_fu > loads when used in an app but my plugin that depends on it can''t.plugin loading is a red herring here. The problem is that has_attachment is being called on the Experts::Photo::CallBacks module rather than on an activerecord class. You need to be doing this call from your self.included callback Fred
On Jul 30, 1:57 pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> plugin loading is a red herring here. The problem is that > has_attachment is being called on the Experts::Photo::CallBacks module > rather than on an activerecord class. You need to be doing this call > from your self.included callbackI don''t know that I would call it a red herring - more like a symptom of not really understanding how to stitch things together. If I understand you correctly, has_attachment can''t be a module callback. It almost isn''t a part of the module at all. Rather it is something the module needs to add to the AR-derived class that is including my module. Yes?
Oh now I see - I had just parked code into the module - not within a method. Dho! With Fred''s pointer and some experimentation, I now have files uploading from my plugin code. The has_attachment code actually needed to go into ClassMethods, like so: module ClassMethods def self.included(model) model.class_eval do has_attachment :storage => :file_system, :path_prefix => ''public/photos'', :content_type => :image, :min_size => 1.kilobyte, :max_size => 3.megabyte, :thumbnails => {:thumbnail => ''x100>''} end end end Have a couple more things to play with - and then I need to see if I can use has_many_polymorphs within my included modules. Thanks Fred!