[noosfero/noosfero][master] 2 commits: plugins: Support plugin to be defined as module instead of object

Bráulio Bhavamitra gitlab at gitlab.com
Sat Jun 13 22:58:57 BRT 2015


Bráulio Bhavamitra pushed to branch master at Noosfero / noosfero


Commits:
682ee5be by Braulio Bhavamitra at 2015-06-13T22:42:32Z
plugins: Support plugin to be defined as module instead of object

This makes possible for a plugin to be defined as module and have its
main class defined inside it with the name Base (e.g. MyPlugin::Base).

The advantages of this is to correctly scope plugins constants inside
the module. There are many conflicts with the core if the plugin is
defined as klass, for example:
 - if you define a MyPlugin::DisplayHelper you'll get the error 'warning: toplevel constant DisplayHelper referenced by MyPlugin::DisplayHelper' and your class won't be loaded unless you put a "require 'my_plugin/display_helper'"
 - `require` is also needed for contants with the sames of constants declared under Noosfero::Plugin. For example, if you define a MyPlugin::Manager or MyPlugin::Settings, Noosfero::Plugin::Manager or Noosfero::Plugin::Settings will be returned instead of your plugin's definition.
 - other hard to debug errors may also happen.

This also encapsulates loading procedures into methods of
Noosfero::Plugin.

- - - - -
9a1c00d4 by Bráulio Bhavamitra at 2015-06-14T01:58:44Z
Merge branch 'plugin-defined-with-module' into 'master'

Support plugin to be defined as module instead of object

This makes possible for a plugin to be defined as module and have its
main class defined inside it with the name Base (e.g. MyPlugin::Base).

The advantages of this is to correctly scope plugins constants inside
the module. There are many conflicts with the core if the plugin is
defined as klass, for example:
 - if you define a MyPlugin::DisplayHelper you'll get the error 'warning: toplevel constant DisplayHelper referenced by MyPlugin::DisplayHelper' and your class won't be loaded unless you put a "require 'my_plugin/display_helper'"
 - `require` is also needed for contants with the sames of constants declared under Noosfero::Plugin. For example, if you define a MyPlugin::Manager or MyPlugin::Settings, Noosfero::Plugin::Manager or Noosfero::Plugin::Settings will be returned instead of your plugin's definition.
 - other hard to debug errors may also happen.

This also encapsulates loading procedures into methods of
Noosfero::Plugin.

See merge request !482

- - - - -


4 changed files:

- lib/noosfero/plugin.rb
- lib/noosfero/plugin/manager.rb
- + lib/noosfero/plugin/parent_methods.rb
- test/unit/plugin_test.rb


Changes:

=====================================
lib/noosfero/plugin.rb
=====================================
--- a/lib/noosfero/plugin.rb
+++ b/lib/noosfero/plugin.rb
@@ -1,4 +1,5 @@
 require_dependency 'noosfero'
+require 'noosfero/plugin/parent_methods'
 
 class Noosfero::Plugin
 
@@ -14,13 +15,9 @@ class Noosfero::Plugin
 
   class << self
 
-    attr_writer :should_load
+    include Noosfero::Plugin::ParentMethods
 
-    # Called for each ActiveRecord class with parents
-    # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix
-    def table_name_prefix
-      @table_name_prefix ||= "#{name.to_s.underscore}_"
-    end
+    attr_writer :should_load
 
     def should_load
       @should_load.nil? && true || @boot
@@ -92,8 +89,14 @@ class Noosfero::Plugin
       end
     end
 
-    def load_plugin(plugin_name)
-      (plugin_name.to_s.camelize + 'Plugin').constantize
+    def load_plugin_identifier identifier
+      klass = identifier.to_s.camelize.constantize
+      klass = klass.const_get :Base if klass.class == Module
+      klass
+    end
+
+    def load_plugin public_name
+      load_plugin_identifier "#{public_name.to_s.camelize}Plugin"
     end
 
     # This is a generic method that initialize any possible filter defined by a
@@ -135,7 +138,7 @@ class Noosfero::Plugin
         filters = [filters]
       end
       filters.each do |plugin_filter|
-        filter_method = (plugin.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]).to_sym
+        filter_method = "#{plugin.identifier}_#{plugin_filter[:method_name]}".to_sym
         controller_class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {}))
         controller_class.send(:define_method, filter_method) do
           instance_exec(&plugin_filter[:block]) if environment.plugin_enabled?(plugin)
@@ -168,38 +171,6 @@ class Noosfero::Plugin
       @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize }
     end
 
-    def public_name
-      self.name.underscore.gsub('_plugin','')
-    end
-
-    def public_path file = '', relative=false
-      File.join "#{if relative then '' else  '/' end}plugins", public_name, file
-    end
-
-    def root_path
-      Rails.root.join('plugins', public_name)
-    end
-
-    def view_path
-      File.join(root_path,'views')
-    end
-
-    # Here the developer should specify the meta-informations that the plugin can
-    # inform.
-    def plugin_name
-      self.name.underscore.humanize
-    end
-    def plugin_description
-      _("No description informed.")
-    end
-
-    def admin_url
-      {:controller => "#{name.underscore}_admin", :action => 'index'}
-    end
-
-    def has_admin_url?
-      File.exists?(File.join(root_path, 'controllers', "#{name.underscore}_admin_controller.rb"))
-    end
   end
 
   def expanded_template(file_path, locals = {})


=====================================
lib/noosfero/plugin/manager.rb
=====================================
--- a/lib/noosfero/plugin/manager.rb
+++ b/lib/noosfero/plugin/manager.rb
@@ -76,7 +76,7 @@ class Noosfero::Plugin::Manager
 
   def enabled_plugins
     @enabled_plugins ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin|
-      plugin.constantize.new(context)
+      Noosfero::Plugin.load_plugin_identifier(plugin).new context
     end
   end
 


=====================================
lib/noosfero/plugin/parent_methods.rb
=====================================
--- /dev/null
+++ b/lib/noosfero/plugin/parent_methods.rb
@@ -0,0 +1,62 @@
+class Noosfero::Plugin
+
+  # Plugins that are defined as modules should extend
+  # this module manually, for example:
+  #   module MyPlugin
+  #     extend Noosfero::Plugin::ParentMethods
+  #   end
+  module ParentMethods
+
+    def identifier
+      @identifier ||= (if self.parents.first.instance_of? Module then self.parents.first else self end).name.underscore
+    end
+
+    def public_name
+      @public_name ||= self.identifier.gsub '_plugin', ''
+    end
+
+    # Here the developer should specify the meta-informations that the plugin can
+    # inform.
+    def plugin_name
+      self.identifier.humanize
+    end
+    def plugin_description
+      _("No description informed.")
+    end
+
+    # Called for each ActiveRecord model with parents
+    # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix
+    def table_name_prefix
+      @table_name_prefix ||= "#{self.identifier}_"
+    end
+
+    def public_path file = '', relative=false
+      File.join "#{if relative then '' else  '/' end}plugins", public_name, file
+    end
+
+    def root_path
+      Rails.root.join('plugins', public_name)
+    end
+
+    def view_path
+      File.join(root_path,'views')
+    end
+
+    def admin_url
+      {:controller => "#{self.identifier}_admin", :action => 'index'}
+    end
+
+    def has_admin_url?
+      File.exists?(File.join(root_path, 'controllers', "#{self.identifier}_admin_controller.rb"))
+    end
+
+    def controllers
+      @controllers ||= Dir.glob("#{self.root_path}/controllers/*/*").map do |controller_file|
+        next unless controller_file =~ /_controller.rb$/
+        controller = File.basename(controller_file).gsub(/.rb$/, '').camelize
+      end.compact
+    end
+
+  end
+
+end


=====================================
test/unit/plugin_test.rb
=====================================
--- a/test/unit/plugin_test.rb
+++ b/test/unit/plugin_test.rb
@@ -23,7 +23,7 @@ class PluginTest < ActiveSupport::TestCase
   end
 
   should 'returns empty hash for class method extra_blocks by default if no blocks are defined on plugin' do
-    
+
     class SomePlugin1 < Noosfero::Plugin
     end
 



View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/99ae59ff68fca6f2c5d41dfeadc0b388dd9dbf97...9a1c00d4886c88286d43c22d1655291d18a0abf0
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150614/8dfcb56d/attachment-0001.html>


More information about the Noosfero-dev mailing list