[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