Commit 06c13aaeed3d5f0ef85ab45b87c084aa43bb49b7
1 parent
2be7f5f4
Exists in
master
and in
28 other branches
Modularizing the hotspot feature
* Every class now can declare that it is able to inlcude hotspots by declaring 'acts_as_having_hotspots'. It's important to note that every class that have hotspots must define an instance method named 'environment' that returns the environment associated with the instance. * Now the enabled_plugins method is centralized in the Thread.current making the plugins instantiation happen only once by Thread. Every request reinstantiate the plugins since every request creates a new Thread. The models that access this method only instantiate it if it wasn't instantiated already. * Since the models doesn't reinstantiate the plugins in the same Thread and the tests run in only one Thread, the tests that have some plugin stuff must clean the instantiation in the teardown.
Showing
8 changed files
with
68 additions
and
26 deletions
Show diff stats
app/controllers/application_controller.rb
1 | 1 | class ApplicationController < ActionController::Base |
2 | 2 | |
3 | 3 | before_filter :change_pg_schema |
4 | + before_filter :detect_stuff_by_domain | |
5 | + before_filter :init_noosfero_plugins | |
4 | 6 | |
5 | 7 | include ApplicationHelper |
6 | 8 | layout :get_layout |
... | ... | @@ -51,8 +53,6 @@ class ApplicationController < ActionController::Base |
51 | 53 | |
52 | 54 | include NeedsProfile |
53 | 55 | |
54 | - before_filter :detect_stuff_by_domain | |
55 | - before_filter :init_noosfero_plugins | |
56 | 56 | attr_reader :environment |
57 | 57 | |
58 | 58 | before_filter :load_terminology | ... | ... |
config/initializers/plugins.rb
... | ... | @@ -0,0 +1,44 @@ |
1 | +module ActsAsHavingHotspots | |
2 | + module ClassMethods | |
3 | + # Adding this feature to a class demands that it defines an instance method | |
4 | + # 'environment' that returns the environment associated with the instance. | |
5 | + def acts_as_having_hotspots | |
6 | + send :include, InstanceMethods | |
7 | + end | |
8 | + | |
9 | + module InstanceMethods | |
10 | + # Dispatches +event+ to each enabled plugin and collect the results. | |
11 | + # | |
12 | + # Returns an Array containing the objects returned by the event method in | |
13 | + # each plugin. This array is compacted (i.e. nils are removed) and flattened | |
14 | + # (i.e. elements of arrays are added to the resulting array). For example, if | |
15 | + # the enabled plugins return 1, 0, nil, and [1,2,3], then this method will | |
16 | + # return [1,0,1,2,3] | |
17 | + # | |
18 | + def dispatch(event, *args) | |
19 | + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact.flatten | |
20 | + end | |
21 | + | |
22 | + # Dispatch without flatten since scopes are executed if you run flatten on them | |
23 | + def dispatch_scopes(event, *args) | |
24 | + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact | |
25 | + end | |
26 | + | |
27 | + def enabled_plugins | |
28 | + Thread.current[:enabled_plugins] ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin_name| | |
29 | + plugin = plugin_name.constantize.new | |
30 | + plugin.context = context | |
31 | + plugin | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + if !method_defined?(:context) | |
36 | + define_method(:context) do | |
37 | + Noosfero::Plugin::Context.new | |
38 | + end | |
39 | + end | |
40 | + end | |
41 | + end | |
42 | +end | |
43 | + | |
44 | +ActiveRecord::Base.send(:extend, ActsAsHavingHotspots::ClassMethods) | ... | ... |
lib/noosfero/plugin/context.rb
lib/noosfero/plugin/manager.rb
1 | 1 | class Noosfero::Plugin::Manager |
2 | 2 | |
3 | - attr_reader :context | |
3 | + extend ActsAsHavingHotspots::ClassMethods | |
4 | + acts_as_having_hotspots | |
4 | 5 | |
5 | - def initialize(controller) | |
6 | - @context = Noosfero::Plugin::Context.new(controller) | |
7 | - end | |
6 | + attr_reader :context | |
8 | 7 | |
8 | + delegate :environment, :to => :context | |
9 | 9 | delegate :each, :to => :enabled_plugins |
10 | 10 | include Enumerable |
11 | 11 | |
12 | - # Dispatches +event+ to each enabled plugin and collect the results. | |
13 | - # | |
14 | - # Returns an Array containing the objects returned by the event method in | |
15 | - # each plugin. This array is compacted (i.e. nils are removed) and flattened | |
16 | - # (i.e. elements of arrays are added to the resulting array). For example, if | |
17 | - # the enabled plugins return 1, 0, nil, and [1,2,3], then this method will | |
18 | - # return [1,0,1,2,3] | |
19 | - # | |
20 | - def dispatch(event, *args) | |
21 | - map { |plugin| plugin.send(event, *args) }.compact.flatten | |
22 | - end | |
23 | - | |
24 | - def enabled_plugins | |
25 | - @enabled_plugins ||= (Noosfero::Plugin.all & context.environment.enabled_plugins).map do |plugin| | |
26 | - p = plugin.constantize.new | |
27 | - p.context = context | |
28 | - p | |
12 | + def initialize(controller) | |
13 | + @context = Noosfero::Plugin::Context.new(controller) | |
14 | + Thread.current[:enabled_plugins] = (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin_name| | |
15 | + plugin = plugin_name.constantize.new | |
16 | + plugin.context = context | |
17 | + plugin | |
29 | 18 | end |
30 | 19 | end |
31 | 20 | ... | ... |
test/unit/person_test.rb
... | ... | @@ -3,6 +3,10 @@ require File.dirname(__FILE__) + '/../test_helper' |
3 | 3 | class PersonTest < ActiveSupport::TestCase |
4 | 4 | fixtures :profiles, :users, :environments |
5 | 5 | |
6 | + def teardown | |
7 | + Thread.current[:enabled_plugins] = nil | |
8 | + end | |
9 | + | |
6 | 10 | def test_person_must_come_form_the_cration_of_an_user |
7 | 11 | p = Person.new(:environment => Environment.default, :name => 'John', :identifier => 'john') |
8 | 12 | assert !p.valid? | ... | ... |
test/unit/plugin_manager_test.rb
... | ... | @@ -10,10 +10,8 @@ class PluginManagerTest < ActiveSupport::TestCase |
10 | 10 | @controller.stubs(:response).returns() |
11 | 11 | @controller.stubs(:environment).returns(@environment) |
12 | 12 | @controller.stubs(:params).returns() |
13 | - @manager = Noosfero::Plugin::Manager.new(@controller) | |
14 | 13 | end |
15 | 14 | attr_reader :environment |
16 | - attr_reader :manager | |
17 | 15 | |
18 | 16 | should 'return the intersection between environment\'s enabled plugins and system available plugins' do |
19 | 17 | class Plugin1 < Noosfero::Plugin; end; |
... | ... | @@ -22,6 +20,7 @@ class PluginManagerTest < ActiveSupport::TestCase |
22 | 20 | class Plugin4 < Noosfero::Plugin; end; |
23 | 21 | environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s]) |
24 | 22 | Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s]) |
23 | + manager = Noosfero::Plugin::Manager.new(@controller) | |
25 | 24 | plugins = manager.enabled_plugins.map { |instance| instance.class.to_s } |
26 | 25 | assert_equal [Plugin1.to_s, Plugin4.to_s], plugins |
27 | 26 | end |
... | ... | @@ -50,6 +49,7 @@ class PluginManagerTest < ActiveSupport::TestCase |
50 | 49 | |
51 | 50 | p1 = Plugin1.new |
52 | 51 | p2 = Plugin2.new |
52 | + manager = Noosfero::Plugin::Manager.new(@controller) | |
53 | 53 | |
54 | 54 | assert_equal [p1.random_event, p2.random_event], manager.dispatch(:random_event) |
55 | 55 | end | ... | ... |
test/unit/profile_test.rb
... | ... | @@ -3,6 +3,10 @@ require File.dirname(__FILE__) + '/../test_helper' |
3 | 3 | class ProfileTest < ActiveSupport::TestCase |
4 | 4 | fixtures :profiles, :environments, :users, :roles, :domains |
5 | 5 | |
6 | + def teardown | |
7 | + Thread.current[:enabled_plugins] = nil | |
8 | + end | |
9 | + | |
6 | 10 | def test_identifier_validation |
7 | 11 | p = Profile.new |
8 | 12 | p.valid? | ... | ... |