mynyml-merb_simple_views 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/LICENSE ADDED
File without changes
data/README ADDED
@@ -0,0 +1,158 @@
1
+ merb_simple_views *ALPHA*
2
+ ==============================
3
+
4
+ WARNING: This plugin is a rewrite of merb-in-file-templates for merb >= 1.0 It
5
+ is very much a work in progress, and is NOT yet stable! Feel free to contribute
6
+ or fork if you are interesting though.
7
+
8
+ UPDATE: Due to the direction the merb project has taken, this plugin's
9
+ development has been put on hold indefinitly.
10
+
11
+
12
+
13
+ A plugin for the Merb framework that allows templates (views) to be defined in
14
+ the same file as the controller (Sinatra style). Especially useful for
15
+ --very-flat apps (making them truly flat), apps that have litle/small view
16
+ code, and for rapid prototyping.
17
+
18
+ ==== Features
19
+ * Seamless integration with #render, #display
20
+ * Respects template reloading
21
+ * Very simple to use
22
+ * Flexible
23
+
24
+ ==== Dependencies
25
+ * Merb > 0.9.4 (?)
26
+ * Rspec to run the specs
27
+
28
+ ==== Examples
29
+ #example for --very-flat app (single file app)
30
+
31
+ #...
32
+ class Application < Merb::Controller; end
33
+ class Products < Application
34
+ def index
35
+ @products = Product.all
36
+ render
37
+ end
38
+ def show
39
+ @product = Product[params[:id]]
40
+ render
41
+ end
42
+ end
43
+
44
+ __END__
45
+ @@ index.html.erb
46
+ <h1>Product List</h1>
47
+ <ul>
48
+ <% for product in @products -%>
49
+ <li><%= product.name %></li>
50
+ <% end -%>
51
+ </ul>
52
+
53
+ @@ show.html.erb
54
+ <h1><%= @product.name %></h1>
55
+
56
+ In-file templates cohabit peacefully with regular external templates. So in the
57
+ above example, show.html.erb could be defined in views/products/show.html.erb
58
+ and both templates will still be picked up normally. In case of a name conflict
59
+ between an in-file and an external template, the external one will take
60
+ precedence and won't be overwritten, keeping it safe from data loss.
61
+
62
+ Template names follow the same rules as regular templates (usually
63
+ action.mime_type.templating_engine).
64
+
65
+ Layouts, stylesheets and javascript can also be placed in in-file templates.
66
+
67
+ #...
68
+
69
+ __END__
70
+ @@ layout/application.css
71
+ #...
72
+
73
+ @@ layout/products.css
74
+ #...
75
+
76
+ @@ stylesheets/application.css
77
+ #...
78
+
79
+ @@ javascripts/jquery.js
80
+ #...
81
+
82
+ ==== Tweaking
83
+ In order to be fed into merb's templating system, in-file templates need to be
84
+ written to external files. This means you will see dynamically created view
85
+ files inside your Merb.dir_for(:view) directory/subdirectories.
86
+
87
+ The directory in which files are stored is chosen based on the templating
88
+ system's native mechanisms, and so merb-in-file-templates will respect any
89
+ changes to it. Therefore if you want to change where template files are stored,
90
+ you can play with Merb.push_path(:view, ...) and the controller's
91
+ #_template_location method.
92
+
93
+ Merb.push_path(:view, Merb.root / 'views')
94
+ class Application
95
+ def _template_location(context, type=nil, controller = controller_name)
96
+ "#{controller}.#{action_name}.#{type}"
97
+ end
98
+ end
99
+
100
+ This will tell Merb to look under the /views directory, for a template named
101
+ products.index.html.erb.
102
+
103
+ want even flatter?
104
+
105
+ Merb.push_path(:view, Merb.root)
106
+ class Application
107
+ def _template_location(context, type=nil, controller=controller_name)
108
+ "view.#{controller}.#{action_name}.#{type}"
109
+ end
110
+ end
111
+
112
+ will give you a template under the root dir called view.products.index.html.erb
113
+ (adding a common prefix, 'view.' in the example above, causes template files to
114
+ show up nicely grouped with ls, file managers, etc, so they look organized even
115
+ without being placed in a subdirectory).
116
+
117
+ If you mix in-file and external templates and you don't want them to be mixed
118
+ in the same directories, you can tell merb-in-file-templates to store its
119
+ templates somewhere else. This is done through the config hash:
120
+
121
+ Merb::Plugins.config[:in_file_templates] = {
122
+ :view_root => '...',
123
+ :stylesheets_root => '...',
124
+ :javascripts_root => '...',
125
+ }
126
+
127
+ For example, you could set
128
+
129
+ :view_root => Merb.root / 'tmp' / 'ift_views'
130
+
131
+ to store your files in merb-root/tmp/ift_views, or
132
+
133
+ :view_root => '/tmp'
134
+
135
+ to store files in your system's tmp directory.
136
+
137
+ Same goes for stylesheets and javascripts, but remember that those need to be
138
+ placed in a public directory, and that they need to be referenced properly from
139
+ within your html header. You can use the controller's
140
+ #ift_dir_for(:stylesheets) and #ift_dir_for(:javascripts) methods to find their
141
+ locations.
142
+
143
+ ==== Rake Task
144
+ TODO
145
+ (cleanup rake task before deployment..)
146
+
147
+ ==== Installation
148
+ TODO
149
+
150
+ ==== Contact
151
+ If you have suggestions, comments, a patch, a git pull request, rants, doc
152
+ fixes/improvements, etc., feel free to contact me: mynyml at gmail,
153
+ irc.freenode.net #rubyonrails, #merb
154
+
155
+ Happy Hacking!
156
+
157
+ -------------------------------------------------------------------------
158
+ Copyright (c) 2008 Martin Aumont (mynyml), released under the MIT license
@@ -0,0 +1,49 @@
1
+ require 'rake/gempackagetask'
2
+ require 'pathname'
3
+ require 'yaml'
4
+
5
+ def gem
6
+ RUBY_1_9 ? 'gem19' : 'gem'
7
+ end
8
+
9
+ def all_except(paths)
10
+ Dir['**/*'] - paths.map {|path| path.strip.gsub(/^\//,'').gsub(/\/$/,'') }
11
+ end
12
+
13
+ spec = Gem::Specification.new do |s|
14
+ s.name = 'merb_simple_views'
15
+ s.version = '0.5.0'
16
+ s.summary = 'Merb plugin that allows defining templates (views, css, js)in the same file as the controller.'
17
+ s.description = 'Merb plugin that allows defining templates (views, css, js)in the same file as the controller.'
18
+ s.author = "Martin Aumont"
19
+ s.email = 'mynyml@gmail.com'
20
+ s.homepage = ''
21
+ s.has_rdoc = true
22
+ s.require_path = "lib"
23
+ s.files = all_except(%w( tmp/* log/* ))
24
+ s.add_dependency 'merb-core >= 1.0'
25
+ end
26
+
27
+ Rake::GemPackageTask.new(spec) do |p|
28
+ p.gem_spec = spec
29
+ end
30
+
31
+
32
+ desc "Remove package products"
33
+ task :clean => :clobber_package
34
+
35
+ desc "Update the gemspec for GitHub's gem server"
36
+ task :gemspec do
37
+ Pathname("#{spec.name}.gemspec").open('w') {|f| f << YAML.dump(spec) }
38
+ end
39
+
40
+ desc "Install gem"
41
+ task :install => [:clobber, :package] do
42
+ sh "#{SUDO} #{gem} install pkg/#{spec.full_name}.gem"
43
+ end
44
+
45
+ desc "Uninstall gem"
46
+ task :uninstall => :clean do
47
+ sh "#{SUDO} #{gem} uninstall -v #{spec.version} -x #{spec.name}"
48
+ end
49
+
data/TODO ADDED
File without changes
@@ -0,0 +1,2 @@
1
+ Autotest.add_discovery { "simpleviews" }
2
+ Autotest.add_discovery { "rspec" }
@@ -0,0 +1,106 @@
1
+ # adaptest from autotest/merb_rspec.rb
2
+ require 'autotest'
3
+
4
+ class RspecCommandError < StandardError; end
5
+
6
+ class Autotest::RspecSimpleviews < Autotest
7
+ def initialize
8
+ super
9
+
10
+ # Ignore any happenings in these directories
11
+ add_exception %r%^\./(?:doc|log|tmp|autotest|bin|\.git|\.autotest)%
12
+
13
+ # Ignore any mappings that Autotest may have already set up
14
+ clear_mappings
15
+
16
+ # run all specs if spec_helper is modified
17
+ add_mapping %r%^spec/spec_helper\.rb% do |_,_|
18
+ all_specs
19
+ end
20
+
21
+ # run all specs if main lib file is modified
22
+ add_mapping %r%^lib/merb_simple_views\.rb% do |_,_|
23
+ all_specs
24
+ end
25
+
26
+ # changing a lib file runs corresponding spec
27
+ add_mapping %r%^lib/merb_simple_views/(.*)\.rb% do |_, m|
28
+ files_matching %r%^spec/.*#{m[1]}_spec\.rb$%
29
+ end
30
+
31
+ # Changing a spec will cause it to run itself
32
+ add_mapping %r%^spec/.*_spec\.rb$% do |filename, _|
33
+ filename
34
+ end
35
+
36
+ end
37
+
38
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39
+
40
+ def failed_results(results)
41
+ results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m)
42
+ end
43
+
44
+ def handle_results(results)
45
+ @failures = failed_results(results)
46
+ @files_to_test = consolidate_failures(@failures)
47
+ @files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red)
48
+ @tainted = !@files_to_test.empty?
49
+ end
50
+
51
+ def consolidate_failures(failed)
52
+ filters = Hash.new { |h,k| h[k] = [] }
53
+ failed.each do |spec, failed_trace|
54
+ if f = test_files_for(failed).find { |f| f =~ /spec\// }
55
+ filters[f] << spec
56
+ break
57
+ end
58
+ end
59
+ filters
60
+ end
61
+
62
+ def make_test_cmd(specs_to_runs)
63
+ [
64
+ ruby,
65
+ "-S",
66
+ spec_command,
67
+ add_options_if_present,
68
+ files_to_test.keys.flatten.join(' ')
69
+ ].join(' ')
70
+ end
71
+
72
+ def add_options_if_present
73
+ File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
74
+ end
75
+
76
+ # Finds the proper spec command to use. Precendence is set in the
77
+ # lazily-evaluated method spec_commands. Alias + Override that in
78
+ # ~/.autotest to provide a different spec command then the default
79
+ # paths provided.
80
+ def spec_command(separator=File::ALT_SEPARATOR)
81
+ unless defined?(@spec_command)
82
+ @spec_command = spec_commands.find { |cmd| File.exists?(cmd) }
83
+
84
+ raise RspecCommandError, "No spec command could be found" unless @spec_command
85
+
86
+ @spec_command.gsub!(File::SEPARATOR, separator) if separator
87
+ end
88
+ @spec_command
89
+ end
90
+
91
+ # Autotest will look for spec commands in the following
92
+ # locations, in this order:
93
+ #
94
+ # * default spec bin/loader installed in Rubygems
95
+ # * any spec command found in PATH
96
+ def spec_commands
97
+ [File.join(Config::CONFIG['bindir'], 'spec'), 'spec']
98
+ end
99
+
100
+ private
101
+
102
+ # Runs +files_matching+ for all specs
103
+ def all_specs
104
+ files_matching %r%^spec/.*_spec\.rb$%
105
+ end
106
+ end
@@ -0,0 +1,33 @@
1
+ if defined?(Merb::Plugins)
2
+ dir = Pathname(__FILE__).dirname / 'merb_simple_views'
3
+
4
+ # Make Merb::RenderMixin's #render and #display methods chainable
5
+ #
6
+ # ==== Notes
7
+ # This is used as a (arguably) more elegant workaround to
8
+ # alias_method_chaining them.
9
+ #
10
+ # "We consider cases of people using alias_method_chain on Merb to be a bug in
11
+ # Merb, and try to find ways to expose enough functionality so it will not be
12
+ # required."
13
+ # -- http://yehudakatz.com/2008/05/22/the-greatest-thing-since-sliced-merb/
14
+ #
15
+ # Ideally those methods would be declared chainable within the RenderMixin
16
+ # itself and this monkey patch wouldn't be needed.
17
+ Merb::RenderMixin.module_eval do
18
+ [:render, :display].each do |name|
19
+ method = instance_method(name)
20
+ self.class.chainable { send(:define_method, name, method) }
21
+ end
22
+ end
23
+
24
+ require dir / 'template_parser'
25
+ require dir / 'mixin'
26
+
27
+ # config options
28
+ Merb::Plugins.config[:simple_views] = {}
29
+
30
+ Merb::BootLoader.after_app_loads do
31
+ Merb::Controller.class_eval { include SimpleViews::Mixin }
32
+ end
33
+ end
@@ -0,0 +1,84 @@
1
+ module SimpleViews
2
+
3
+ TEMPLATES = {}
4
+
5
+ # Adds SimpleViews functionality to a Merb controller, allowing templates
6
+ # defined in the controller's file to serve as views. See README for more.
7
+ module Mixin
8
+ attr_reader :_template_parser
9
+
10
+ def initialize
11
+ @_template_parser = SimpleViews::TemplateParser.new
12
+ super
13
+ end
14
+
15
+ # In addition to default #render behaviour, parse simple views defined in
16
+ # controller's file and render them when requested, or render external
17
+ # templates otherwise.
18
+ #
19
+ # ==== Notes
20
+ # 1. Turned into a chainable method in merb_simple_views.rb
21
+ # 2. Uses a VirtualFile to trick template engines.
22
+ #
23
+ # ==== Parameters
24
+ # See Merb::RenderMixin#render
25
+ #
26
+ # ==== Options
27
+ # See Merb::RenderMixin#render
28
+ #
29
+ # ==== Returns
30
+ # See Merb::RenderMixin#render
31
+ #
32
+ # ==== Raises
33
+ # See Merb::RenderMixin#render
34
+ #
35
+ # ==== Alternatives
36
+ # See Merb::RenderMixin#render
37
+ #
38
+ # :api: public
39
+ def render(*args)
40
+ tpls_file = (@__caller_info__ || __caller_info__).first.first
41
+ self._template_parser.load(tpls_file).parse.each do |template_name, raw_content|
42
+ # no controller name if absolute view path
43
+ ctrl_name = template_name.match(/^\//) ? nil : self.controller_name
44
+ path = Merb.dir_for(:view) / self._template_location(template_name.gsub(/^\//,''), nil, ctrl_name)
45
+ file = VirtualFile.new(raw_content, path)
46
+ TEMPLATES[path.to_s] = file
47
+ end
48
+ super
49
+ end
50
+
51
+ # Wrap #display and store caller info so that #render (called internally by
52
+ # #display) knows what file to fetch template data from.
53
+ #
54
+ # ==== Notes
55
+ # Turned into a chainable method in merb_simple_views.rb
56
+ #
57
+ # ==== Parameters
58
+ # See Merb::RenderMixin#display
59
+ #
60
+ # ==== Options
61
+ # See Merb::RenderMixin#display
62
+ #
63
+ # ==== Returns
64
+ # See Merb::RenderMixin#display
65
+ #
66
+ # ==== Raises
67
+ # See Merb::RenderMixin#display
68
+ #
69
+ # ==== Alternatives
70
+ # See Merb::RenderMixin#display
71
+ #
72
+ # :api: public
73
+ def display(*args)
74
+ @__caller_info__ = __caller_info__
75
+ super
76
+ end
77
+ end
78
+ end
79
+
80
+ module Merb::Template
81
+ def self.load_template_io(path)
82
+ super || template_extensions.map {|ext| SimpleViews::TEMPLATES["#{path}.#{ext}"] }.compact.first
83
+ end
84
+ end
@@ -0,0 +1,93 @@
1
+ module SimpleViews
2
+ class TemplateParser
3
+ # templates as a string, directly extracted from the file.
4
+ attr_accessor :raw_templates
5
+ alias :raw :raw_templates
6
+ alias :raw= :raw_templates=
7
+
8
+ # templates as a {'name' => 'content'} hash
9
+ attr_accessor :parsed_templates
10
+ alias :parsed :raw_templates
11
+ alias :parsed= :raw_templates=
12
+
13
+ def initialize
14
+ self.raw_templates = ''
15
+ self.parsed_templates = {}
16
+ end
17
+
18
+ # Read a file and fetch its __END__ section, if any.
19
+ #
20
+ # ==== Parameters
21
+ # file<String,Pathname>:: File to find in-file templates in
22
+ #
23
+ # ==== Returns
24
+ # self
25
+ #
26
+ # :api: public
27
+ def load(file='')
28
+ file = Pathname(file)
29
+ if file.exist?
30
+ parts = file.read.split(/^__END__$/)
31
+ if parts.size > 1
32
+ self.raw_templates = parts[1].lstrip
33
+ end
34
+ end
35
+ self
36
+ end
37
+
38
+ # Parse templates string and extract template names and contents.
39
+ #
40
+ # Template names must be preceded with '@@', appear alone on their line,
41
+ # and follow the same conventions regular templates do. They can also be
42
+ # disabled by simply commenting out their name.
43
+ #
44
+ # ==== Parameters
45
+ # file<String,Pathname>:: File to find in-file templates in
46
+ #
47
+ # ==== Returns
48
+ # Hash:: Parsed templates as {'name' => 'content'}
49
+ #
50
+ # ==== Examples
51
+ #
52
+ # #posts_controller.rb
53
+ # [...]
54
+ # __END__
55
+ # @@ index.html.erb
56
+ # posts
57
+ #
58
+ # @@ show.html.erb
59
+ # post01
60
+ #
61
+ # #=> {'index.html.erb' => "posts", 'show.html.erb' => "post01"}
62
+ #
63
+ # To disable a template, comment out its name:
64
+ #
65
+ # __END__
66
+ # #@@ index.html.erb
67
+ # posts
68
+ #
69
+ # #=> {}
70
+ #
71
+ # ==== Notes
72
+ # Also stores the result in self.parsed_templates
73
+ #
74
+ # :api: public
75
+ def parse(file='')
76
+ self.load(file) if file
77
+ templates, current, ignore = {}, nil, false
78
+ self.raw_templates.each_line do |line|
79
+ if matches = line.strip.match(/^\s*(\#)*\s*@@\s*(.*)/)
80
+ ignore = (matches[1] && matches[1].match(/^#/)) and next #skip commented out templates
81
+ templates[current = matches[2]] = ''
82
+ elsif ignore
83
+ next
84
+ elsif current
85
+ templates[current] << line
86
+ end
87
+ end
88
+ # remove trailing witespace off every template body and template name
89
+ self.parsed_templates = templates.each {|key,value| templates[key.chomp.gsub(/[[:blank:]]|\t/,'')] = value.rstrip }
90
+ self.parsed_templates
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,160 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Simple Views" do
4
+
5
+ before(:all) do
6
+ Merb.root.should == Pathname(__FILE__).dirname.parent.expand_path.to_s
7
+ views_dir = Pathname(Merb.root / "spec/fixtures/views")
8
+ views_dir.mkdir unless views_dir.directory?
9
+ Merb.push_path(:view, views_dir, "**/*")
10
+ end
11
+
12
+ before(:each) do
13
+ class Posts < Merb::Controller
14
+ def index() render end
15
+ def edit() render end
16
+ def quote() render end
17
+ def nohaz() render end
18
+ def random() render end
19
+ def show
20
+ obj = Object.new; def obj.to_html() '<b>x</b>' end
21
+ display(obj)
22
+ end
23
+ def new
24
+ obj = Object.new; def obj.to_html() '<b>y</b>' end
25
+ display(obj)
26
+ end
27
+ end
28
+ class Topics < Merb::Controller
29
+ def index() render end
30
+ def quote() render end
31
+ end
32
+ # -----
33
+ @posts = Posts.new(fake_request)
34
+ @topics = Topics.new(fake_request)
35
+ # -----
36
+ clean_view_dir!
37
+ end
38
+
39
+ it "should be injected in Merb::Controller" do
40
+ Merb::Controller.included_modules.should include(SimpleViews::Mixin)
41
+ end
42
+
43
+ describe "parsing templates" do
44
+
45
+ it "should parse in-file templates on render" do
46
+ @posts._dispatch(:index)
47
+ @posts._template_parser.parsed_templates['index.html.erb'].should == "kittehs"
48
+ @posts.body.should == "kittehs"
49
+ end
50
+
51
+ it "should parse in-file templates on display" do
52
+ @posts._dispatch(:show)
53
+ @posts._template_parser.parsed_templates['show.html.erb'].should == "kitteh-01"
54
+ @posts.body.should == "kitteh-01"
55
+ end
56
+
57
+ it "should parse absolute paths" do
58
+ @posts._dispatch(:quote)
59
+ @posts._template_parser.parsed_templates['/posts/quote.html.erb'].should == "<i>kitteh-01</i>"
60
+ @posts.body.should == "<i>kitteh-01</i>"
61
+ end
62
+
63
+ it "should let template engines parse views" do
64
+ @posts._dispatch(:random)
65
+ @posts._template_parser.parsed_templates['/posts/random.html.erb'].should == "kitteh-<%= '07' %>"
66
+ @posts.body.should == "kitteh-07"
67
+ end
68
+
69
+ it "should respect changes to #_template_location" do
70
+ def @posts._template_location(context, type=nil, controller=controller_name)
71
+ "#{controller}.#{action_name}.#{type}"
72
+ end
73
+ @posts._dispatch(:index)
74
+ @posts.body.should == "tiny kittehs"
75
+ end
76
+
77
+ describe "with template reloading" do
78
+
79
+ it "should reload templates when code reloading is on" do
80
+ Merb::Config[:reload_templates] = true
81
+ # -----
82
+ @posts._dispatch(:index)
83
+ @posts.body.should == "kittehs"
84
+ # -----
85
+ @posts._template_parser.stub!(:parsed_templates).and_return({'index.html.erb' => 'swapped'})
86
+ # -----
87
+ @posts._dispatch(:index)
88
+ @posts.body.should == "swapped"
89
+ end
90
+
91
+ it "should not reload templates when code reloading is off" do
92
+ Merb::Config[:reload_templates] = false
93
+ # -----
94
+ @posts._dispatch(:index)
95
+ @posts.body.should == "kittehs"
96
+ # -----
97
+ @posts._template_parser.stub!(:parsed_templates).and_return({'index.html.erb' => 'swapped'})
98
+ # -----
99
+ @posts._dispatch(:index)
100
+ @posts.body.should == "kittehs"
101
+ end
102
+ end
103
+
104
+ describe "falling back to default behaviour" do
105
+
106
+ it "should delegate to regular render control flow when no in-file template exists" do
107
+ write_template('edit.html.erb', "<i>ohaie!</i>", @posts)
108
+ @posts._dispatch(:edit)
109
+ @posts.body.should == "<i>ohaie!</i>"
110
+ end
111
+
112
+ it "should delegate to regular display control flow when no in-file template exists" do
113
+ @posts._dispatch(:new)
114
+ @posts.body.should == "<b>y</b>"
115
+ end
116
+
117
+ it "should raise exception when template is not found" do
118
+ lambda {
119
+ @posts._dispatch(:nohaz)
120
+ }.should raise_error(Merb::ControllerExceptions::TemplateNotFound)
121
+ end
122
+ end
123
+
124
+ describe "with multiple controllers" do
125
+
126
+ it "should pick up templates from the same file" do
127
+ @posts._dispatch(:quote)
128
+ @posts.body.should == "<i>kitteh-01</i>"
129
+ @topics._dispatch(:quote)
130
+ @topics.body.should == "<i>ceilingcat</i>"
131
+ end
132
+
133
+ it "should allow different controllers to use the same, relative template" do
134
+ @posts._dispatch(:index)
135
+ @posts.body.should == "kittehs"
136
+ @topics._dispatch(:index)
137
+ @topics.body.should == "kittehs"
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ __END__
144
+ @@ index.html.erb
145
+ kittehs
146
+
147
+ @@ show.html.erb
148
+ kitteh-01
149
+
150
+ @@ /posts/random.html.erb
151
+ kitteh-<%= '07' %>
152
+
153
+ @@ /posts/quote.html.erb
154
+ <i>kitteh-01</i>
155
+
156
+ @@ /topics/quote.html.erb
157
+ <i>ceilingcat</i>
158
+
159
+ @@ /posts.index.html.erb
160
+ tiny kittehs
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,51 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'merb-core'
6
+ require 'merb_simple_views'
7
+
8
+ begin
9
+ require 'ruby-debug'
10
+ rescue LoadError, RuntimeError
11
+ # i can haz dibugz plz?
12
+ end
13
+
14
+ Merb.start :environment => 'test', :adapter => 'runner'
15
+
16
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
+ # Core Extensions
18
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19
+ # This might cause errors to slip into specs, but it beats using fixtures.
20
+ class String
21
+ def unindent
22
+ indent = self.select {|line| !line.strip.empty? }.map {|line| line.index(/[^\s]/) }.compact.min
23
+ self.gsub(/^[[:blank:]]{#{indent}}/, '')
24
+ end
25
+ def unindent!
26
+ self.replace(self.unindent)
27
+ end
28
+ end
29
+
30
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31
+ # Helpers
32
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33
+ module Helpers
34
+ def write_template(name, content, controller)
35
+ view_path = Merb.dir_for(:view) / controller.controller_name / name
36
+ view_path.dirname.mkdir
37
+ Kernel.open(view_path, 'w+') {|file| file.write(content) }
38
+ end
39
+
40
+ def clean_view_dir!
41
+ FileUtils.rm_rf( Pathname.glob(Merb.dir_for(:view) / "*") )
42
+ end
43
+ end
44
+
45
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46
+ # Config
47
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48
+ Spec::Runner.configure do |config|
49
+ config.include Merb::Test::RequestHelper
50
+ config.include Helpers
51
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Parser" do
4
+
5
+ before(:each) do
6
+ @parser = SimpleViews::TemplateParser.new.load(__FILE__)
7
+ end
8
+
9
+ it "should load in-file templates" do
10
+ @parser.raw_templates.should match(/ohaie/)
11
+ end
12
+
13
+ describe "when parsing template strings" do
14
+
15
+ it "should split templates at @@ marks" do
16
+ @parser.raw = %|
17
+ @@ index
18
+ kittehs
19
+ @@ show
20
+ kitteh1
21
+ |.unindent
22
+ @parser.parse.size.should == 2
23
+ @parser.parse['index'].strip.should == 'kittehs'
24
+ @parser.parse['show'].strip.should == 'kitteh1'
25
+ end
26
+
27
+ it "should remove trailing witespace off every template" do
28
+ @parser.raw = %|
29
+ @@ index
30
+
31
+ kittehs \t\n
32
+ |.unindent
33
+ @parser.parse['index'].should_not match(/\t\n$/)
34
+ @parser.parse['index'].should match(/^\n/)
35
+ end
36
+
37
+ it "should not be bothered by amount of spaces or tabs between marker and template name" do
38
+ @parser.raw = %|
39
+ @@index
40
+ kittehs
41
+ @@\t\sshow
42
+ kitteh1
43
+ |.unindent
44
+ @parser.parse['index'].should_not be_nil
45
+ @parser.parse['show'].should_not be_nil
46
+ @parser.parse["\t\sshow"].should be_nil
47
+ end
48
+ end
49
+ end
50
+
51
+ __END__
52
+ ohaie
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mynyml-merb_simple_views
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Martin Aumont
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-14 21:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: merb-core >= 1.0
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Merb plugin that allows defining templates (views, css, js)in the same file as the controller.
26
+ email: mynyml@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - CHANGELOG
35
+ - log
36
+ - lib
37
+ - lib/merb_simple_views.rb
38
+ - lib/merb_simple_views
39
+ - lib/merb_simple_views/mixin.bk.rb
40
+ - lib/merb_simple_views/cache.rb
41
+ - lib/merb_simple_views/cache.bk.rb
42
+ - lib/merb_simple_views/merbtasks.rb
43
+ - lib/merb_simple_views/merbtasks.bk.rb
44
+ - lib/merb_simple_views/mixin.rb
45
+ - lib/merb_simple_views/template_parser.rb
46
+ - lib/merb_simple_views.bk.rb
47
+ - LICENSE
48
+ - README
49
+ - Rakefile
50
+ - MYTODO
51
+ - draft
52
+ - TODO
53
+ - autotest
54
+ - autotest/rspec_simpleviews.rb
55
+ - autotest/discover.rb
56
+ - autotest/rspec_simpleviews.bk.rb
57
+ - spec
58
+ - spec/spec_helper.rb
59
+ - spec/mixin_spec.bk.rb
60
+ - spec/mixin_spec.rb
61
+ - spec/fixtures
62
+ - spec/fixtures/views
63
+ - spec/fixtures/controller3.rb
64
+ - spec/spec.opts
65
+ - spec/template_parser_spec.rb
66
+ has_rdoc: true
67
+ homepage: ""
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.2.0
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: Merb plugin that allows defining templates (views, css, js)in the same file as the controller.
92
+ test_files: []
93
+