Commit 71015018b67f3a77c8876cace01c60fb581d81f0
1 parent
1f128345
Exists in
master
and in
29 other branches
r222@sede: terceiro | 2007-07-28 15:54:13 -0300
ActionItem0: implementing a better interface for the old flexible_template git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@226 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
15 changed files
with
318 additions
and
0 deletions
Show diff stats
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +require 'rake' | ||
2 | +require 'rake/testtask' | ||
3 | +require 'rake/rdoctask' | ||
4 | + | ||
5 | +desc 'Default: run unit tests.' | ||
6 | +task :default => :test | ||
7 | + | ||
8 | +desc 'Test the design plugin.' | ||
9 | +Rake::TestTask.new(:test) do |t| | ||
10 | + t.libs << 'lib' | ||
11 | + t.pattern = 'test/**/*_test.rb' | ||
12 | + t.verbose = true | ||
13 | +end | ||
14 | + | ||
15 | +desc 'Generate documentation for the design plugin.' | ||
16 | +Rake::RDocTask.new(:rdoc) do |rdoc| | ||
17 | + rdoc.rdoc_dir = 'rdoc' | ||
18 | + rdoc.title = 'Design' | ||
19 | + rdoc.options << '--line-numbers' << '--inline-source' | ||
20 | + rdoc.rdoc_files.include('README') | ||
21 | + rdoc.rdoc_files.include('lib/**/*.rb') | ||
22 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +require 'design' | ||
2 | + | ||
3 | +class ActionController::Base | ||
4 | + | ||
5 | + # Declares that this controller uses design plugin to generate its layout. | ||
6 | + # See the plugin README for options that can be passed to this method. | ||
7 | + def self.design(config = {}) | ||
8 | + if (config.has_key?(:holder) && config.has_key?(:fixed)) || (!config.has_key?(:holder) && !config.has_key?(:fixed)) | ||
9 | + raise ArgumentError.new("You must supply either <tt>:holder</tt> or <tt>:fixed</tt> to design.") | ||
10 | + end | ||
11 | + | ||
12 | + @design_plugin_config = config | ||
13 | + | ||
14 | + include Design | ||
15 | + end | ||
16 | + | ||
17 | + # declares this controller as a design editor, including in it all the | ||
18 | + # functionalities to do that (besides those for using a design). Accepts the | ||
19 | + # same options as design. | ||
20 | + def self.design_editor(config = {}) | ||
21 | + self.design(config) | ||
22 | + include Design::Editor | ||
23 | + end | ||
24 | + | ||
25 | +end |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +# Install hook code here |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +require 'design/fixed_design_holder' | ||
2 | +require 'design/proxy_design_holder' | ||
3 | + | ||
4 | +require 'design/helper' | ||
5 | +require 'design/editor' | ||
6 | + | ||
7 | +module Design | ||
8 | + | ||
9 | + # gets the Design object for this controller | ||
10 | + def design | ||
11 | + @design_plugin_data ||= Hash.new | ||
12 | + data = @design_plugin_data | ||
13 | + | ||
14 | + return data[:design] if data.has_key?(:design) | ||
15 | + | ||
16 | + config = self.class.instance_variable_get("@design_plugin_config") | ||
17 | + | ||
18 | + if config.has_key?(:holder) | ||
19 | + holder_variable_name = config[:holder] | ||
20 | + data[:design] = Design::ProxyDesignHolder.new(self.instance_variable_get("@#{holder_variable_name}")) | ||
21 | + else | ||
22 | + options = (config[:fixed].kind_of? Hash) ? config[:fixed] : {} | ||
23 | + data[:design] = Design::FixedDesignHolder.new(options) | ||
24 | + end | ||
25 | + | ||
26 | + data[:design] # redundant, but makes more clear the return value | ||
27 | + end | ||
28 | + protected :design | ||
29 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +module Design | ||
2 | + | ||
3 | + class FixedDesignHolder | ||
4 | + attr_reader :template, :theme, :icon_theme, :boxes | ||
5 | + def initialize(options = {}) | ||
6 | + @template = options[:template] || 'default' | ||
7 | + @theme = options[:theme] || 'default' | ||
8 | + @icon_theme = options[:icon_theme] || 'default' | ||
9 | + @boxes = options[:boxes] || default_boxes | ||
10 | + end | ||
11 | + | ||
12 | + # creates some default boxes | ||
13 | + def default_boxes | ||
14 | + box1 = Box.new | ||
15 | + box2 = Box.new | ||
16 | + box2.blocks << MainBlock.new | ||
17 | + box3 = Box.new | ||
18 | + | ||
19 | + [box1, box2, box3] | ||
20 | + end | ||
21 | + private :default_boxes | ||
22 | + end | ||
23 | + | ||
24 | +end | ||
25 | + |
@@ -0,0 +1,43 @@ | @@ -0,0 +1,43 @@ | ||
1 | +module Design | ||
2 | + | ||
3 | + # This class uses an external holder object to hold the details of the | ||
4 | + # design, and proxies all access to the template data to it. This object can | ||
5 | + # be any object that responds to the following methods: | ||
6 | + # | ||
7 | + # * +template+ | ||
8 | + # * +template=+ | ||
9 | + # * +theme+ | ||
10 | + # * +theme=+ | ||
11 | + # * +icon_theme+ | ||
12 | + # * +icon_theme=+ | ||
13 | + # * +boxes+ | ||
14 | + # * +boxes=+ | ||
15 | + # | ||
16 | + # These methods must implement get/set semantics for atrributes with their | ||
17 | + # names, and can be implemented with +attr_accessor+, as ActiveRecord | ||
18 | + # columns, or event explicity by writing the methods and storing the values | ||
19 | + # wherever you want. | ||
20 | + # | ||
21 | + # +template+, +theme+ and +icon_theme+ must return (and accept in the | ||
22 | + # setters) strings, while +boxes+ must be an array of Box objects. | ||
23 | + class ProxyDesignHolder | ||
24 | + | ||
25 | + attr_reader :holder | ||
26 | + | ||
27 | + # creates a new proxy for +holder+ | ||
28 | + def initialize(holder) | ||
29 | + @holder = holder | ||
30 | + end | ||
31 | + | ||
32 | + # proxies all calls to +template+, +theme+, +icon_theme+ and +boxes+ (as | ||
33 | + # well as their setters counterparts) to the holder object | ||
34 | + def method_missing(method_id, *args) | ||
35 | + if method_id.to_s =~ /^(template|theme|icon_theme|boxes)=?$/ | ||
36 | + holder.send(method_id, *args) | ||
37 | + else | ||
38 | + raise NoMethodError.new("Design has no method \"#{method_id}\"") | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
43 | +end |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +require File.join(File.dirname(__FILE__), 'test_helper') | ||
2 | + | ||
3 | +class FixedDesignHolderTest < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_design_should_include_design_module | ||
6 | + assert FixedDesignTestController.included_modules.include?(Design) | ||
7 | + end | ||
8 | + | ||
9 | + def test_design_editor_should_include_design_and_design_editor_module | ||
10 | + assert DesignEditorTestController.included_modules.include?(Design) | ||
11 | + assert DesignEditorTestController.included_modules.include?(Design::Editor) | ||
12 | + end | ||
13 | + | ||
14 | + def test_should_not_accept_no_holder_and_no_fixed | ||
15 | + assert_raise ArgumentError do | ||
16 | + DesignEditorTestController.design | ||
17 | + end | ||
18 | + end | ||
19 | + def test_should_not_accept_both_holder_and_fixed | ||
20 | + assert_raise ArgumentError do | ||
21 | + DesignEditorTestController.design :holder => 'something', :fixed => true end | ||
22 | + end | ||
23 | + | ||
24 | +end |
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +require File.join(File.dirname(__FILE__), 'test_helper') | ||
2 | + | ||
3 | +class FixedDesignHolderTest < Test::Unit::TestCase | ||
4 | + | ||
5 | + include Design | ||
6 | + | ||
7 | + def test_explicit_design | ||
8 | + controller = FixedDesignTestController.new | ||
9 | + assert_kind_of Design::FixedDesignHolder, controller.design | ||
10 | + assert_equal 'some_template', controller.design.template | ||
11 | + assert_equal 'some_theme', controller.design.theme | ||
12 | + assert_equal 'some_icon_theme', controller.design.icon_theme | ||
13 | + assert_equal [FixedDesignTestController::BOX1, FixedDesignTestController::BOX2, FixedDesignTestController::BOX3], controller.design.boxes | ||
14 | + end | ||
15 | + | ||
16 | + def test_explicit_design_should_have_sensible_defaults | ||
17 | + controller = FixedDesignDefaultTestController.new | ||
18 | + assert_kind_of Design::FixedDesignHolder, controller.design | ||
19 | + assert_equal 'default', controller.design.template | ||
20 | + assert_equal 'default', controller.design.theme | ||
21 | + assert_equal 'default', controller.design.icon_theme | ||
22 | + assert_kind_of Array, controller.design.boxes | ||
23 | + assert_equal 3, controller.design.boxes.size | ||
24 | + end | ||
25 | + | ||
26 | + def test_should_not_be_able_to_assign_template | ||
27 | + # FixedDesignHolder does not implement assigment, on purpose | ||
28 | + assert_raise NoMethodError do | ||
29 | + FixedDesignHolder.new.template = 'break' | ||
30 | + end | ||
31 | + end | ||
32 | + | ||
33 | + def test_should_not_be_able_to_assign_theme | ||
34 | + # FixedDesignHolder does not implement assigment, on purpose | ||
35 | + assert_raise NoMethodError do | ||
36 | + FixedDesignHolder.new.theme = 'break' | ||
37 | + end | ||
38 | + end | ||
39 | + | ||
40 | + def test_should_not_be_able_to_assign_icon_theme | ||
41 | + assert_raise NoMethodError do | ||
42 | + FixedDesignHolder.new.icon_theme = 'break' | ||
43 | + end | ||
44 | + end | ||
45 | + | ||
46 | + def test_should_not_be_able_to_assign_boxes | ||
47 | + assert_raise NoMethodError do | ||
48 | + FixedDesignHolder.new.boxes = [] | ||
49 | + end | ||
50 | + end | ||
51 | + | ||
52 | + | ||
53 | +end |
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +require File.join(File.dirname(__FILE__), 'test_helper') | ||
2 | + | ||
3 | + | ||
4 | +class ProxyDesignHolderTest < Test::Unit::TestCase | ||
5 | + | ||
6 | + # FIXME: rewrite this test with mocha | ||
7 | + def test_design_should_interact_with_sample_holder | ||
8 | + design = Design::ProxyDesignHolder.new(SampleHolderForTestingProxyDesignHolder.new) | ||
9 | + design.template = 'bli' | ||
10 | + assert_equal 'bli', design.template | ||
11 | + design.theme = 'bli' | ||
12 | + assert_equal 'bli', design.theme | ||
13 | + design.icon_theme = 'bli' | ||
14 | + assert_equal 'bli', design.icon_theme | ||
15 | + design.boxes = [] | ||
16 | + assert_equal [], design.boxes | ||
17 | + end | ||
18 | + | ||
19 | + def test_design_user_controller_should_get_a_proper_design | ||
20 | + controller = ProxyDesignHolderTestController.new | ||
21 | + design = controller.send(:design) | ||
22 | + design.template = 'bli' | ||
23 | + assert_equal 'bli', design.template | ||
24 | + design.theme = 'bli' | ||
25 | + assert_equal 'bli', design.theme | ||
26 | + design.icon_theme = 'bli' | ||
27 | + assert_equal 'bli', design.icon_theme | ||
28 | + design.boxes = [] | ||
29 | + assert_equal [], design.boxes | ||
30 | + end | ||
31 | + | ||
32 | +end |
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +ENV["RAILS_ENV"] = "test" | ||
2 | +require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment") | ||
3 | + | ||
4 | +require 'test/unit' | ||
5 | + | ||
6 | +######################## | ||
7 | +# test clases below here | ||
8 | +######################## | ||
9 | + | ||
10 | +class FixedDesignTestController < ActionController::Base | ||
11 | + | ||
12 | + BOX1 = Box.new | ||
13 | + BOX2 = Box.new | ||
14 | + BOX3 = Box.new | ||
15 | + | ||
16 | + design :fixed => { | ||
17 | + :template => 'some_template', | ||
18 | + :theme => 'some_theme', | ||
19 | + :icon_theme => 'some_icon_theme', | ||
20 | + :boxes => [ BOX1, BOX2, BOX3 ], | ||
21 | + } | ||
22 | +end | ||
23 | + | ||
24 | +class FixedDesignDefaultTestController < ActionController::Base | ||
25 | + design :fixed => true | ||
26 | +end | ||
27 | + | ||
28 | +class SampleHolderForTestingProxyDesignHolder | ||
29 | + attr_accessor :template, :theme, :icon_theme, :boxes | ||
30 | +end | ||
31 | + | ||
32 | +class ProxyDesignHolderTestController < ActionController::Base | ||
33 | + design :holder => 'sample_object' | ||
34 | + def initialize | ||
35 | + @sample_object = SampleHolderForTestingProxyDesignHolder.new | ||
36 | + end | ||
37 | +end | ||
38 | + | ||
39 | +class DesignEditorTestController < ActionController::Base | ||
40 | + design_editor :holder => 'sample_object' | ||
41 | + def initialize | ||
42 | + @sample_object = SampleHolderForTestingProxyDesignHolder.new | ||
43 | + end | ||
44 | +end |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +# Uninstall hook code here |