view_driver 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ spec/debug.log
@@ -0,0 +1,138 @@
1
+ view_driver helps to dry up views using sublayouts and sections.
2
+
3
+ == Sublayouts
4
+
5
+ Remember when you had to create one more layout which generally was almost the same as the default one for your application or your view templates contained duplicated html-markup.
6
+
7
+ This is what sublayouts are for.
8
+
9
+ === How to use sublayouts
10
+
11
+
12
+ * Replace <%= yield %> or <%= @content_for_layout %> in your layout with <%= yield_with_sublayouts %>
13
+ * Put your sublayout into app/views/sublayouts
14
+ * Set the instance variable called @sublayout in the controller using 'sublayout' before_filter or manually
15
+
16
+ For example, if you've written something like
17
+
18
+ sublayout 'edit', :only => [:new, :create, :edit, :update]
19
+
20
+ in a controller and created a sublayout called app/views/sublayouts/edit.html.erb with <%= yield %> in it, the specified actions will be rendered within that sublayout.
21
+
22
+ The action's output will be inserted right in the layout if the sublayout has not been defined.
23
+
24
+ By default sublayouts live in app/views/sublayouts but you can pick any other folder e.g. 'layouts', creating an initializer with:
25
+
26
+ ViewDriver::SUBLAYOUTS_DIR = "layouts"
27
+
28
+ Sublayouts are quite suitable with sections.
29
+
30
+ == Sections
31
+
32
+ Sections are fragments of view similar to partials, which can be easily used in the application because they are well-structured and can be defined in the controller.
33
+
34
+ Imagine that in the layout there is a sidebar which can be the same or vary in different places. For example it can have no banner for one controller, or extra-blocks for another one. You can manage it with sections.
35
+
36
+ === Naming and location
37
+
38
+ Default templates for a section are (by precedence):
39
+
40
+ 1) for an action:
41
+ "app/views/#{@controller.controller_path}/#{@controller.action_name}_#{section_name}.html.erb"
42
+ 2) for a controller:
43
+ "app/views/#{@controller.controller_path}/default_#{section_name}.html.erb"
44
+ 3) for an application:
45
+ "app/views/sections/default_#{section_name}.html.erb"
46
+
47
+ You can change a default sections' location for an application defining ViewDriver::SECTIONS_DIR.
48
+
49
+ === Rendering
50
+
51
+ For rendering there is a helper render_section, which can be put into your view file (it can be a layout, a sublayout or any other view file as well):
52
+
53
+ <%= render_section(:sidebar) %>
54
+
55
+ It will try to find the first template from the defaults above and render it, so if there is no default file for an action, it will take default for a controller and then for an application. If none of them are found it will render nothing.
56
+
57
+ ==== Templates extensions
58
+
59
+ By default ViewDriver looks for templates with the "html.erb" extension. You can change this behaviour by defining ViewDriver::SECTIONS_TEMPLATES_EXTENSIONS, for example:
60
+
61
+ ViewDriver::SECTIONS_TEMPLATES_EXTENSIONS = ["haml"]
62
+
63
+ # be careful because it will require to check if a template exists for both extensions
64
+ ViewDriver::SECTIONS_TEMPLATES_EXTENSIONS = ["html.erb", "rhtml"]
65
+
66
+ ViewDriver caches templates' existence in production, check out ViewDriver::SectionsCollection#template_exists?
67
+
68
+ === How to change templates for sections
69
+
70
+ You can do it by a 'sections' before_filter or manually (check out ViewDriver::ActionControllerExtensions::ClassMethods#sections for details).
71
+
72
+ Templates defined by the 'sections' before_filter is of higher precendence than the default ones.
73
+
74
+ Since the 'sections' is a before_filter it can be chained and controlled by standard options: :only, :except, :if, and :unless.
75
+
76
+ It will be easier to get it through the examples.
77
+
78
+ So let's assume that a controller for a current request is PagesController.
79
+
80
+ ==== Default values for all sections
81
+
82
+ # sections will be taken first from :show action
83
+ sections 'show'
84
+ # so when you call render_section(:header) it will render 'pages/show_header' and if it doesn't exist it will look through the default chain
85
+
86
+ # if you pass the default value and the options hash, values will be merged
87
+ # so this will take all the sections from users folder except sidebar, which will be default
88
+ sections proc{|c| "users/#{c.action_name}"}, :sidebar => 'pages/default'
89
+
90
+ ==== If you pass false as a template, it won't render section at all
91
+
92
+ # it won't render sections at all if a user is not logged in
93
+ sections false, :unless => proc{|c| c.logged_in?}
94
+
95
+ # it won't render sidebar section for the particular actions
96
+ sections :sidebar => false, :only => [:new, :edit, :update, :create]
97
+
98
+ ==== Other examples
99
+
100
+ # :sidebar will be 'unlogged_sidebar' if a user is not logged in and 'logged_sidebar' otherwise
101
+ sections :sidebar => :sidebar_section
102
+
103
+ protected
104
+ def sidebar_section
105
+ logged_in? ? 'logged' : 'unlogged'
106
+ end
107
+
108
+ # the sections :sidebar and :navigations will be taken from the 'views/users' folder for :galleries and :users actions
109
+ sections :sidebar => 'users/show', :navigation => 'users/index', :only => [:galleries, :users]
110
+
111
+ # this sets all the sections to be default from 'users' folder for all requests passing the specified proc
112
+ sections 'users/default', :if => proc{|instance| !%w{static sessions}.include?(instance.controller_name)}
113
+
114
+ Besides strings sections before_filter accepts procs and methods (passed as symbols). Check out the sections method in the ActionControllerExtensions module.
115
+
116
+ == Add-ons
117
+
118
+ view_driver also comes with a helper method called 'classes' used to set css-classes or any other attributes conditionally.
119
+
120
+ <!-- will add 'logged' class if logged_in? method returns true -->
121
+ <%= content_tag(:div, 'test', :class => classes('default-class', ['logged', logged_in?])) %>
122
+
123
+ it also modifies image_tag a bit in order to use blank :alt attribute by default and duplicate it as :title attribute
124
+
125
+ >> image_tag 'quake.gif'
126
+ => "<img alt='' src='/images/quake.gif' />"
127
+ >> image_tag 'quake.gif', :alt => 'foo'
128
+ => "<img alt='foo' src='/images/quake.gif' title='foo' />"
129
+ >> image_tag 'quake.gif', :alt => 'foo', :title => 'bar'
130
+ => "<img alt='foo' src='/images/quake.gif' title='bar' />"
131
+
132
+ == Installation
133
+
134
+ script/plugin install git://github.com/macovsky/view_driver.git
135
+
136
+ == Help
137
+
138
+ If you have any troubles using this plugin, you can ping me through robotector AT gmail.
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "view_driver"
8
+ gemspec.summary = "Helps dry up Rails-views using sublayouts and sections"
9
+ gemspec.description = "Helps dry up Rails-views using sublayouts and sections"
10
+ gemspec.email = "robotector@gmail.com"
11
+ gemspec.homepage = "http://github.com/macovsky/view_driver"
12
+ gemspec.authors = ["Macovsky"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ # require 'rake'
20
+ # require 'spec/rake/spectask'
21
+ #
22
+ # desc 'Default: run specs.'
23
+ # task :default => :spec
24
+ #
25
+ # desc 'Run the specs'
26
+ # Spec::Rake::SpecTask.new(:spec) do |t|
27
+ # t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
28
+ # t.spec_files = FileList['spec/**/*_spec.rb']
29
+ # end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/rails/init.rb"
@@ -0,0 +1,12 @@
1
+ module ViewDriver
2
+ !defined?(SUBLAYOUTS_DIR) && SUBLAYOUTS_DIR = 'sublayouts'
3
+ !defined?(SECTIONS_DIR) && SECTIONS_DIR = 'sections'
4
+ !defined?(SECTIONS_TEMPLATES_EXTENSIONS) && SECTIONS_TEMPLATES_EXTENSIONS = ['html.erb']
5
+ end
6
+
7
+ require 'view_driver/normalized_section_template'
8
+ require 'view_driver/sections'
9
+ require 'view_driver/sections_collection'
10
+ require 'view_driver/action_controller_extensions'
11
+ require 'view_driver/view_helpers'
12
+ require 'view_driver/image_tag_extension'
@@ -0,0 +1,80 @@
1
+ module ViewDriver
2
+ module ActionControllerExtensions
3
+ FILTER_OPTIONS = [:only, :except, :if, :unless]
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.cattr_accessor :existing_sections
8
+ base.send :include, InstanceMethods
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ # Filter to define sections in a controller
14
+ def sections(*args)
15
+ method = "_sections_#{args.to_s.gsub(/[^a-z_]/, '_')}"
16
+ options = args.extract_options!
17
+ raise(ArgumentError, "Only one argument is allowed") if args.size > 1
18
+
19
+ before_filter method, options.slice(*FILTER_OPTIONS)
20
+
21
+ define_method method do
22
+ @sections_collection ||= SectionsCollection.new(self)
23
+ section_templates = options.except(*FILTER_OPTIONS)
24
+ section_templates.each{|k,v| section_templates[k] = parse_argument_for_sections(v)}
25
+ @sections_collection << Sections.new(parse_argument_for_sections(args.first), section_templates)
26
+ end
27
+
28
+ protected method.to_sym
29
+ end
30
+
31
+ # Filter to define a sublayout in a controller
32
+ def sublayout(*args)
33
+ method = "_sublayout_#{args.to_s.gsub(/[^a-z_]/, '_')}"
34
+ options = args.extract_options!
35
+
36
+ before_filter method, options.slice(*FILTER_OPTIONS)
37
+
38
+ define_method method do
39
+ @sublayout = case (sublayout = args.first)
40
+ when Symbol
41
+ send(sublayout)
42
+ when Proc
43
+ sublayout.call(self)
44
+ else
45
+ sublayout
46
+ end
47
+ end
48
+ protected method.to_sym
49
+ end
50
+
51
+ def default_section_templates(section, action_name)
52
+ [action_name, 'default'].map{|action| controller_path + "/#{action}_#{section}"} + [ViewDriver::SECTIONS_DIR + "/default_#{section}"]
53
+ end
54
+
55
+ end
56
+
57
+ module InstanceMethods
58
+
59
+ def default_section_templates(section, action = nil)
60
+ self.class.default_section_templates(section, action || action_name)
61
+ end
62
+
63
+ def parse_argument_for_sections(arg)
64
+ case arg
65
+ when Symbol
66
+ send(arg)
67
+ when Proc
68
+ arg.call(self)
69
+ when String, NilClass, FalseClass
70
+ arg
71
+ else
72
+ raise ArgumentError, "Unsupported argument"
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+ ActionController::Base.send(:include, ViewDriver::ActionControllerExtensions)
@@ -0,0 +1,12 @@
1
+ module ActionView
2
+ module Helpers
3
+ module AssetTagHelper
4
+ def image_tag_with_title(source, options = {})
5
+ options[:alt] ||= ''
6
+ image_tag_without_title(source, options[:alt].blank? ? options : options.merge(:title => options[:title] || options[:alt]))
7
+ end
8
+
9
+ alias_method_chain :image_tag, :title
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module ViewDriver
2
+ module ObjectExtensions
3
+ def normalized_section_template(section)
4
+ self
5
+ end
6
+ end
7
+
8
+ module StringExtensions
9
+ def normalized_section_template(section)
10
+ self !~ /_#{section}$/ ? self + "_#{section}" : self
11
+ end
12
+ end
13
+ end
14
+
15
+ Object.send :include, ViewDriver::ObjectExtensions
16
+ String.send :include, ViewDriver::StringExtensions
@@ -0,0 +1,35 @@
1
+ module ViewDriver
2
+ class Sections
3
+ attr_reader :templates
4
+
5
+ def initialize(default_value, options = {})
6
+ @templates = convert_to_hash(default_value, options)
7
+ end
8
+
9
+ def template(section)
10
+ @templates[section].normalized_section_template(section)
11
+ end
12
+
13
+ def ==(sections)
14
+ @templates == sections.templates && @templates.default == sections.templates.default
15
+ end
16
+
17
+ private
18
+
19
+ def convert_to_hash(default_value, options)
20
+ raise(ArgumentError, "No arguments were provided") if default_value.nil? && options.blank?
21
+
22
+ hash = case default_value
23
+ when Hash, HashWithIndifferentAccess
24
+ HashWithIndifferentAccess.new.merge(default_value)
25
+ when String, NilClass, FalseClass
26
+ HashWithIndifferentAccess.new(default_value)
27
+ else
28
+ raise(ArgumentError, 'Unsupported argument')
29
+ end
30
+ # using merge! because simple merge deletes default value
31
+ hash.merge!(options)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ module ViewDriver
2
+
3
+ class SectionsCollection < Array
4
+ attr_reader :controller
5
+
6
+ def initialize(controller)
7
+ super()
8
+ @controller = controller
9
+ end
10
+
11
+ def templates(section)
12
+ defined_template = defined_template(section)
13
+ return [] if defined_template == false
14
+ ([defined_template] + @controller.default_section_templates(section)).compact
15
+ end
16
+
17
+ def defined_template(section)
18
+ template = nil
19
+ each do |sections|
20
+ candidate = sections.template(section)
21
+ template = candidate unless candidate.nil?
22
+ end
23
+ prepend_controller_path(template)
24
+ end
25
+
26
+ def prepend_controller_path(template)
27
+ template.is_a?(String) && !template.include?("/") ? File.join(@controller.controller_path, template) : template
28
+ end
29
+
30
+ def template_to_render(section)
31
+ templates(section).find{|template| template_exists?(template)}
32
+ end
33
+
34
+ def template_exists?(template)
35
+ ViewDriver::SECTIONS_TEMPLATES_EXTENSIONS.any? do |ext|
36
+ basename = template + ".#{ext}"
37
+ file = File.join(RAILS_ROOT, 'app', 'views', basename)
38
+ unless @controller.perform_caching
39
+ File.exists?(file)
40
+ else
41
+ ApplicationController.existing_sections ||= {}
42
+ ApplicationController.existing_sections[basename].nil? && ApplicationController.existing_sections[basename] = File.exists?(file)
43
+ ApplicationController.existing_sections[basename]
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,56 @@
1
+ module ViewDriver
2
+ module ViewHelpers
3
+
4
+ # Renders section :section for the current controller and action
5
+ def render_section(section)
6
+ @sections_collection ||= SectionsCollection.new(@controller)
7
+
8
+ if RAILS_ENV == "development"
9
+ _time1, _time2 = nil, nil
10
+ _time1 = Time.now
11
+ end
12
+
13
+ if template = @sections_collection.template_to_render(section)
14
+ result = render(:file => template)
15
+ if RAILS_ENV == "development"
16
+ _time2 = Time.now
17
+ logger.debug "Rendered section #{template} (#{((_time2 - _time1)*1000).round(1)}ms)"
18
+ end
19
+ result
20
+ elsif RAILS_ENV == "development"
21
+ logger.debug "Missing section #{section}"
22
+ "<!-- Missing section #{section} -->"
23
+ end
24
+ end
25
+
26
+ # Renders sublayouts
27
+ # replace <%= yield %> or <%= @content_for_layout %> with it to use sublayouts
28
+ def yield_with_sublayouts
29
+ unless @sublayout.blank?
30
+ sublayout_file = @sublayout.include?('/') ? @sublayout : File.join(SUBLAYOUTS_DIR, @sublayout)
31
+ RAILS_ENV == 'development' && logger.debug("Rendering template within sublayout #{sublayout_file}")
32
+ render :file => sublayout_file
33
+ else
34
+ @content_for_layout
35
+ end
36
+ end
37
+
38
+ # classes is to set css-classes or other attributes conditionally
39
+ # classes("class-without-conditions", ["logged-class", logged_in?], "third-class-without-conditions")
40
+ def classes(*pairs)
41
+ glued_classes = []
42
+ pairs.each do |pair|
43
+ next if pair.blank?
44
+ arr = Array(pair)
45
+ raise ArgumentError, "css_class or [css_class, condition] are expected (got #{pair.inspect})" if arr.size.zero? || arr.size > 2
46
+ glued_classes << arr[0] if arr[1] || arr.size == 1
47
+ end
48
+ glued_classes.any? ? glued_classes.join(" ") : nil
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ ActionView::Base.module_eval do
55
+ include ViewDriver::ViewHelpers
56
+ end
Binary file
@@ -0,0 +1 @@
1
+ require 'view_driver'
@@ -0,0 +1,122 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ViewDriver::SectionsCollection do
4
+ include ViewDriverSpecHelper
5
+
6
+ before :each do
7
+ @controller = create_controller
8
+ @controller.action_name = 'show'
9
+ @collection = ViewDriver::SectionsCollection.new(@controller)
10
+ end
11
+
12
+ context "defined_template" do
13
+ it "should return nil when collection is blank" do
14
+ @collection.defined_template(:sidebar).should be_nil
15
+ end
16
+
17
+ it "should return last value when only there was only one controller involved" do
18
+ @collection << ViewDriver::Sections.new('show', {})
19
+ @collection.defined_template(:sidebar).should == 'pages/show_sidebar'
20
+ end
21
+
22
+ context "with multiple sections" do
23
+ it "should return last not null value" do
24
+ @collection << ViewDriver::Sections.new('show', {})
25
+ @collection << ViewDriver::Sections.new(:sidebar => 'new')
26
+ @collection.defined_template(:sidebar).should == 'pages/new_sidebar'
27
+ @collection.defined_template(:subnavi).should == 'pages/show_subnavi'
28
+ end
29
+
30
+ it "should return false value as last" do
31
+ @collection << ViewDriver::Sections.new(:sidebar => 'new')
32
+ @collection << ViewDriver::Sections.new(:sidebar => false)
33
+ @collection.defined_template(:sidebar).should be_false
34
+ end
35
+ end
36
+ end
37
+
38
+ context "templates" do
39
+ it "should return empty collection if section is set to false" do
40
+ @collection << ViewDriver::Sections.new(false, {})
41
+ @collection.templates(:sidebar).should be_empty
42
+ end
43
+
44
+ it "should return default templates if sections aren't set" do
45
+ @collection.templates(:sidebar).should == @controller.default_section_templates(:sidebar)
46
+ end
47
+
48
+ context "with defined sections" do
49
+ before :each do
50
+ @collection << ViewDriver::Sections.new(nil, {:sidebar => 'users/show'})
51
+ end
52
+
53
+ it "should return a template defined by section + default templates for defined section" do
54
+ @collection.templates(:sidebar).should == ['users/show_sidebar'] + @collection.controller.default_section_templates(:sidebar)
55
+ end
56
+
57
+ it "should return default templates for undefined section" do
58
+ @collection.templates(:header).should == @controller.default_section_templates(:header)
59
+ end
60
+ end
61
+
62
+ context "with multi defined sections" do
63
+ it "should return defined template + default templates" do
64
+ @collection << ViewDriver::Sections.new('create')
65
+ @collection << ViewDriver::Sections.new(nil, {:sidebar => 'new'})
66
+
67
+ @collection.templates(:header).should == ['pages/create_header'] + @controller.default_section_templates(:header)
68
+ @collection.templates(:sidebar).should == ['pages/new_sidebar'] + @controller.default_section_templates(:sidebar)
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'template_to_render' do
74
+ it "should return first existing template" do
75
+ @collection << ViewDriver::Sections.new('create')
76
+ @collection.should_receive(:template_exists?).with('pages/create_sidebar').and_return(true)
77
+ @collection.template_to_render(:sidebar).should == 'pages/create_sidebar'
78
+ end
79
+
80
+ it "should return nil if there weren't any templates" do
81
+ @collection.should_receive(:templates).with(:header).and_return([])
82
+ @collection.template_to_render(:header).should be_nil
83
+ end
84
+
85
+ it "should return nil if there weren't any existing templates" do
86
+ @collection.should_receive(:template_exists?).exactly(3).and_return(false)
87
+ @collection.template_to_render(:sidebar).should be_nil
88
+ end
89
+ end
90
+
91
+ context 'template_exists?' do
92
+
93
+ it "should ask File.exists? with possible template extensions" do
94
+ File.should_receive(:exists?).with(File.join(RAILS_ROOT, "app", "views", "pages/show_sidebar.html.erb")).and_return(true)
95
+ @collection.template_exists?("pages/show_sidebar").should be_true
96
+ end
97
+
98
+ context "with caching" do
99
+ before(:each) do
100
+ @controller.should_receive(:perform_caching).at_most(2).and_return(true)
101
+ end
102
+
103
+ after(:each) do
104
+ ApplicationController.existing_sections = nil
105
+ end
106
+
107
+ it "should save the value" do
108
+ File.should_receive(:exists?).with(File.join(RAILS_ROOT, "app", "views", "pages/show_sidebar.html.erb")).and_return(true)
109
+ @collection.template_exists?("pages/show_sidebar").should be_true
110
+ ApplicationController.existing_sections.should == {"pages/show_sidebar.html.erb" => true}
111
+ end
112
+
113
+ it "should not ask the file exist" do
114
+ ApplicationController.existing_sections = {"pages/show_sidebar.html.erb" => true}
115
+ @collection.template_exists?("pages/show_sidebar").should be_true
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,40 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ViewDriver::Sections do
4
+ include ViewDriverSpecHelper
5
+
6
+ context "equality" do
7
+ before :each do
8
+ @sections = ViewDriver::Sections.new(nil, {:header => 'show'})
9
+ end
10
+
11
+ it "should be equal to another object with the same templates" do
12
+ @sections.should == ViewDriver::Sections.new(nil, {:header => 'show'})
13
+ end
14
+
15
+ it "should not be equal to objects with different templates" do
16
+ @sections.should_not == ViewDriver::Sections.new(false)
17
+ @sections.should_not == ViewDriver::Sections.new(false, {:header => 'show'})
18
+ @sections.should_not == ViewDriver::Sections.new(nil, {:header => 'temp'})
19
+ end
20
+ end
21
+
22
+ context 'template' do
23
+ it "should return default value for unexisting section" do
24
+ ViewDriver::Sections.new(false).template(:header).should be_false
25
+ ViewDriver::Sections.new(false, {:header => 'users/show'}).template(:sidebar).should be_false
26
+ ViewDriver::Sections.new(nil, {:header => 'users/show'}).template(:sidebar).should be_nil
27
+ ViewDriver::Sections.new("show").template(:sidebar).should == "show_sidebar"
28
+ end
29
+
30
+ it "should add section's name" do
31
+ ViewDriver::Sections.new(nil, {:header => 'show'}).template(:header).should == "show_header"
32
+ ViewDriver::Sections.new(nil, {:header => 'users/show'}).template(:header).should == "users/show_header"
33
+ end
34
+
35
+ it "should not add section's name" do
36
+ ViewDriver::Sections.new(nil, {:header => 'show_header'}).template(:header).should == 'show_header'
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,30 @@
1
+ begin
2
+ require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
3
+ rescue LoadError
4
+ puts "You need to install rspec in your base app"
5
+ exit
6
+ end
7
+
8
+ plugin_spec_dir = File.dirname(__FILE__)
9
+ # ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
10
+
11
+ module ViewDriverSpecHelper
12
+ def create_controller(controller_path = 'pages', super_class = ApplicationController, &block)
13
+ controller = Class.new(super_class)
14
+
15
+ controller.class_eval do
16
+ class_eval "def self.controller_path; '#{controller_path}'; end"
17
+
18
+ %w(index show new).each do |action|
19
+ class_eval <<-EOV, __FILE__, __LINE__
20
+ def #{action}
21
+ end
22
+ EOV
23
+ end
24
+ end
25
+
26
+ controller.class_eval(&block) if block
27
+ controller.new
28
+ end
29
+ end
30
+
@@ -0,0 +1,94 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ActionController do
4
+ include ViewDriverSpecHelper
5
+
6
+ context "default_section_templates" do
7
+ before :each do
8
+ @controller = create_controller
9
+ @controller.action_name = 'show'
10
+ @default_section_templates = ['pages/show_sidebar', 'pages/default_sidebar', "#{ViewDriver::SECTIONS_DIR}/default_sidebar"]
11
+ end
12
+
13
+ it "should return default templates" do
14
+ @controller.default_section_templates(:sidebar).should == @default_section_templates
15
+ @controller.class.default_section_templates(:sidebar, 'show').should == @default_section_templates
16
+ end
17
+ end
18
+
19
+ context "sections" do
20
+ it "should define sections" do
21
+ @controller = create_controller do
22
+ sections :sidebar => 'show'
23
+ end
24
+
25
+ get 'index'
26
+ @controller.assigns["sections_collection"].should == (ViewDriver::SectionsCollection.new(@controller) << ViewDriver::Sections.new(nil, {:sidebar => 'show'}))
27
+ end
28
+
29
+ it "should define multiple sections" do
30
+ @controller = create_controller('admin/pages') do
31
+ sections :sidebar => 'show'
32
+ sections :header => 'default'
33
+ end
34
+
35
+ get 'index'
36
+ @controller.assigns["sections_collection"].should == (ViewDriver::SectionsCollection.new(@controller) << ViewDriver::Sections.new(nil, {:sidebar => 'show'}) << ViewDriver::Sections.new(nil, {:header => 'default'}))
37
+ end
38
+
39
+ it "should define sections using proc" do
40
+ @controller = create_controller do
41
+ sections proc{|c| "users/#{c.action_name}" }
42
+ end
43
+
44
+ get 'index'
45
+ @controller.assigns["sections_collection"].should == (ViewDriver::SectionsCollection.new(@controller) << ViewDriver::Sections.new('users/index'))
46
+ end
47
+
48
+ it "should define sections using method" do
49
+ @controller = create_controller do
50
+ sections :change_sections
51
+
52
+ define_method 'change_sections' do
53
+ "users/#{action_name}"
54
+ end
55
+ end
56
+
57
+ get 'index'
58
+ @controller.assigns["sections_collection"].should == (ViewDriver::SectionsCollection.new(@controller) << ViewDriver::Sections.new('users/index'))
59
+ end
60
+ end
61
+
62
+ context "sublayout" do
63
+ it "should define sublayout" do
64
+ @controller = create_controller do
65
+ sublayout 'particular'
66
+ end
67
+
68
+ get 'index'
69
+ @controller.assigns["sublayout"].should == 'particular'
70
+ end
71
+
72
+ it "should define sublayout using proc" do
73
+ @controller = create_controller do
74
+ sublayout proc{|c| "#{c.action_name}_particular"}
75
+ end
76
+
77
+ get 'index'
78
+ @controller.assigns["sublayout"].should == 'index_particular'
79
+ end
80
+
81
+ it "should define sublayout using method" do
82
+ @controller = create_controller do
83
+ sublayout :change_sublayout
84
+
85
+ define_method 'change_sublayout' do
86
+ "#{action_name}_particular"
87
+ end
88
+ end
89
+
90
+ get 'index'
91
+ @controller.assigns["sublayout"].should == 'index_particular'
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ViewDriver::ViewHelpers do
4
+ include ViewDriver::ViewHelpers
5
+ include ViewDriverSpecHelper
6
+
7
+ context "render_section" do
8
+ before(:each) do
9
+ @controller = create_controller
10
+ @sections_collection = ViewDriver::SectionsCollection.new(@controller)
11
+ end
12
+
13
+ it "should return nil if no templates available" do
14
+ @sections_collection.should_receive(:template_to_render).with(:sidebar).and_return(nil)
15
+ render_section(:sidebar).should be_nil
16
+ end
17
+
18
+ it "should return rendered template" do
19
+ @sections_collection.should_receive(:template_to_render).with(:sidebar).and_return('pages/default_sidebar')
20
+ should_receive(:render).with(:file => 'pages/default_sidebar').and_return('rendered pages/default_sidebar')
21
+ render_section(:sidebar).should == 'rendered pages/default_sidebar'
22
+ end
23
+ end
24
+
25
+ context "yield_with_sublayouts" do
26
+ it "should return @content_for_layout if sublayout wasn't defined" do
27
+ yield_with_sublayouts.should be_nil
28
+ end
29
+
30
+ it "should return rendered template" do
31
+ @sublayout = 'default'
32
+ should_receive(:render).with(:file => File.join(ViewDriver::SUBLAYOUTS_DIR, 'default')).and_return('rendered sublayout')
33
+ yield_with_sublayouts.should == 'rendered sublayout'
34
+ end
35
+ end
36
+
37
+ context "classes" do
38
+ it "should return default classes" do
39
+ classes("default1", "default2").should == "default1 default2"
40
+ end
41
+
42
+ it "should return default classes and classes whose conditions were true" do
43
+ classes("default", ["one", true], ["two", false]).should == "default one"
44
+ end
45
+
46
+ it "should return nil if all the conditions were false" do
47
+ classes(["one", false], ["two", false]).should be_nil
48
+ end
49
+
50
+ it "should return nil if nothing has been provided" do
51
+ classes.should be_nil
52
+ end
53
+
54
+ it "should return nil if nil class has been provided" do
55
+ classes(nil).should be_nil
56
+ end
57
+
58
+ it "should raise an error if more than 2 elements have been provided" do
59
+ lambda do
60
+ classes('class', ['1', '2', '3'])
61
+ end.should raise_error(ArgumentError)
62
+ end
63
+ end
64
+
65
+ context "image_tag" do
66
+ it "should include empty alt tag" do
67
+ image_tag('i.gif').should include('alt=""')
68
+ end
69
+
70
+ it "should duplicate alt's value to title" do
71
+ image_tag('i.gif', :alt => 'alt').should include('alt="alt"')
72
+ image_tag('i.gif', :alt => 'alt').should include('title="alt"')
73
+ end
74
+
75
+ it "should set title's own value" do
76
+ image_tag('i.gif', :title => 'title').should include('alt=""')
77
+ image_tag('i.gif', :title => 'title').should include('title="title"')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{view_driver}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Macovsky"]
12
+ s.date = %q{2009-12-07}
13
+ s.description = %q{Helps dry up Rails-views using sublayouts and sections}
14
+ s.email = %q{robotector@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "init.rb",
24
+ "lib/view_driver.rb",
25
+ "lib/view_driver/action_controller_extensions.rb",
26
+ "lib/view_driver/image_tag_extension.rb",
27
+ "lib/view_driver/normalized_section_template.rb",
28
+ "lib/view_driver/sections.rb",
29
+ "lib/view_driver/sections_collection.rb",
30
+ "lib/view_driver/view_helpers.rb",
31
+ "pkg/view_driver-0.1.0.gem",
32
+ "rails/init.rb",
33
+ "spec/sections_collection_spec.rb",
34
+ "spec/sections_spec.rb",
35
+ "spec/spec_helper.rb",
36
+ "spec/view_driver_action_controller_extensions_spec.rb",
37
+ "spec/view_helpers_spec.rb",
38
+ "view_driver.gemspec"
39
+ ]
40
+ s.homepage = %q{http://github.com/macovsky/view_driver}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.5}
44
+ s.summary = %q{Helps dry up Rails-views using sublayouts and sections}
45
+ s.test_files = [
46
+ "spec/sections_collection_spec.rb",
47
+ "spec/sections_spec.rb",
48
+ "spec/spec_helper.rb",
49
+ "spec/view_driver_action_controller_extensions_spec.rb",
50
+ "spec/view_helpers_spec.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ else
59
+ end
60
+ else
61
+ end
62
+ end
63
+
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: view_driver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Macovsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-07 00:00:00 +03:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Helps dry up Rails-views using sublayouts and sections
17
+ email: robotector@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - .gitignore
26
+ - README.rdoc
27
+ - Rakefile
28
+ - VERSION
29
+ - init.rb
30
+ - lib/view_driver.rb
31
+ - lib/view_driver/action_controller_extensions.rb
32
+ - lib/view_driver/image_tag_extension.rb
33
+ - lib/view_driver/normalized_section_template.rb
34
+ - lib/view_driver/sections.rb
35
+ - lib/view_driver/sections_collection.rb
36
+ - lib/view_driver/view_helpers.rb
37
+ - pkg/view_driver-0.1.0.gem
38
+ - rails/init.rb
39
+ - spec/sections_collection_spec.rb
40
+ - spec/sections_spec.rb
41
+ - spec/spec_helper.rb
42
+ - spec/view_driver_action_controller_extensions_spec.rb
43
+ - spec/view_helpers_spec.rb
44
+ - view_driver.gemspec
45
+ has_rdoc: true
46
+ homepage: http://github.com/macovsky/view_driver
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Helps dry up Rails-views using sublayouts and sections
73
+ test_files:
74
+ - spec/sections_collection_spec.rb
75
+ - spec/sections_spec.rb
76
+ - spec/spec_helper.rb
77
+ - spec/view_driver_action_controller_extensions_spec.rb
78
+ - spec/view_helpers_spec.rb