view_driver 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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