liquidizer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/README.rdoc ADDED
@@ -0,0 +1,187 @@
1
+ = Liquidizer
2
+
3
+ Liquidizer is a gem for Ruby on Rails that allows to render pages using templates stored in the
4
+ database. It uses liquid (http://www.liquidmarkup.org/) templating system (thus the name),
5
+ because it's easy to use, extend and it's safe to edit by users.
6
+
7
+ One example of when you might want to use it is this: Let's say you want to have a blogging
8
+ system where people can create their blogs about kittens, ninjas or vampires. Using this gem,
9
+ you can allow them to edit the look and feel of their blog using just their browser. Every
10
+ blog can have it's own set of templates.
11
+
12
+
13
+ == Installation
14
+
15
+ It's hosted on http://gemcutter.org. Add it to your source list if you don't have it already:
16
+
17
+ sudo gem source --add http://gemcutter.org
18
+
19
+ Then install:
20
+
21
+ sudo gem install liquidizer
22
+
23
+ And add this to your config/environment.rb:
24
+
25
+ config.gem 'liquidizer'
26
+
27
+ == How to use
28
+
29
+ First you have to specify which actions of which controllers should be liquified (rendered
30
+ with loadable liquid templates). To do that, use the +liquify+ controller macro:
31
+
32
+ class PostController < ApplicationController
33
+ # This will apply the templates to all actions in this controller.
34
+ liquify
35
+ end
36
+
37
+ If you want to liquify only some actions, but leave the others to be rendered using standard
38
+ Rails means, do this:
39
+
40
+ class PostController < ApplicationController
41
+ # Liquify only :show and :index.
42
+ liquify :show, :index
43
+ end
44
+
45
+ By default, Liquidizer will infer liquid template names from the controller and action name
46
+ in the same way Rails does. So action index in controller PostsController will have
47
+ template called "posts/index". Namespaced controllers work too: index in Blog::PostsController
48
+ will have template "blog/posts/index". This, however, can be overriden:
49
+
50
+
51
+ class PostController < ApplicationController
52
+ # This will liquify only show, but will use template called "awesome_show_template"
53
+ liquify :show, :as => 'awesome_show_template'
54
+ end
55
+
56
+ The +liquify+ macro is inherited, so if you want to apply liquid templates to all actions
57
+ in all controller, put it into ApplicationController. You can fine-tune it in derived
58
+ controllers, if you want:
59
+
60
+ class ApplicationController < ActionController::Base
61
+ liquify
62
+ end
63
+
64
+ class PostsController < ApplicationController
65
+ liquify :show, :as => 'kickass_show'
66
+ liquify :index, :as => 'hardcore_index'
67
+ end
68
+
69
+ To liquify also layouts, use the +liquify_layout+ macro:
70
+
71
+ class ApplicationController < ActionController::Base
72
+ # This will use layout called "layout"
73
+ liquify_layout
74
+
75
+ # This will use layout called "awesome_kickass_layout"
76
+ liquify_layout :as => "awesome_kickass_layout"
77
+ end
78
+
79
+ The last step is to tell Liquidizer where to load the liquid templates from. The way to implement
80
+ this is completely up to you. For example, you can associate the templates with the Blog model
81
+ (to follow the blog example) and have something like current_blog, which is loaded by the
82
+ current subdomain.
83
+
84
+ In any case, you need to provide a +current_liquid_templates+ method,
85
+ which should return collection of liquid templates to use. This method should return something
86
+ that responds at least to +find_by_name+ which returns an object that responds to +content+
87
+ which returns a string containing the liquid template.
88
+
89
+ The easies way to do this, is to have a +LiquidTemplate+ model and return a collections of
90
+ those in the +current_liquid_templates+. Liquidizer provides one such model for you,
91
+ but you will probably want to use your own. To make your life easier, there is a module
92
+ Liquidizer::LiquidTemplate which you can include into your template model to extend it with
93
+ some helpful methods (see the docs for more info):
94
+
95
+ class Blog < ActiveRecord::Base
96
+ has_many :liquid_templates
97
+ end
98
+
99
+ # The
100
+ class LiquidTemplate < ActiveRecord::Base
101
+ include Liquidizer::LiquidTemplate
102
+ belongs_to :blog
103
+ end
104
+
105
+ class ApplicationController < ActionController::Base
106
+ private
107
+
108
+ def current_liquid_templates
109
+ current_blog.liquid_templates
110
+ end
111
+ end
112
+
113
+ And that's it. You are now ready to kick asses!
114
+
115
+ == Instance variables
116
+
117
+ All instance variables that you assign in the controller are automatically available in the
118
+ liquid templates. The variable will be automatically wrapped in a "drop", if necessary
119
+ (please check the liquid docs for more details about what types can be passed directly to
120
+ liquid templates and what are drops). For a class +Foo+, a +FooDrop+ will be used if it
121
+ exists. If variable is not compatible with liquid and there is no corresponding drop class, it
122
+ won't be passed to the template.
123
+
124
+ Example:
125
+
126
+ A controller:
127
+
128
+ class PostsController < ActiveRecord::Base
129
+ liquify
130
+
131
+ def show
132
+ @post = current_blog.posts.find(params[:id])
133
+ end
134
+ end
135
+
136
+ A drop:
137
+
138
+ class PostDrop < Liquid::Drop
139
+ def initialize(post)
140
+ @post = post
141
+ end
142
+
143
+ def title
144
+ filter_nasty_stuff(@post.title)
145
+ end
146
+ end
147
+
148
+ Then you can do this in your liquid template:
149
+
150
+ <h1>{{ post.title }}</h1>
151
+
152
+ <!-- more stuff ... -->
153
+
154
+ And the post.title will call PostDrop#title, filtering all nasty stuff.
155
+
156
+ The way how variables are wrapped with drops can be completelly customized by overriding the
157
+ +dropify+ method.
158
+
159
+ == Default templates
160
+
161
+ The Liquidizer::LiquidTemplate module gives your model capability to fallback to a default
162
+ template, if one is not found in the database. The default templates are stored in
163
+ db/liquid_templates. You can configure this location by setting the Liquidizer.template_path:
164
+
165
+ Liqduidizer.template_path = Rails.root.join('app', 'views', 'liquid_templates')
166
+
167
+ == TODO
168
+
169
+ There are several possible improvements to this gem:
170
+
171
+ - Extend it so it can handle different template systems in addition (unlikely, since I don't
172
+ need it and can't be bothered :) )
173
+
174
+ - The Rails 3 has improved ActionView API and as far as I understand, abstracts away the
175
+ concept of template storage. Taking advantage of this could potentialy simplify this gem.
176
+ Also, support Rails 3 in general would be nice.
177
+
178
+ - This does some nasty hacks into the ActionController::Base's render method. That method
179
+ originaly has quite liberal API, allowing to specify it's parameters in many ways. To make
180
+ this gem simple, some of those ways were sacrificed. Would be nice to support them too.
181
+
182
+ Potentialy many more. In any case, it's open source project (MIT), so no fear, fork me and
183
+ hack away!
184
+
185
+ == Legal stuff
186
+
187
+ Copyright (c) 2010 Adam Cigánek <adam.ciganek@gmail.com>. Released under the MIT License: www.opensource.org/licenses/mit-license.php
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ desc 'Default: run unit tests.'
5
+ task :default => :test
6
+
7
+ desc 'Run unit tests.'
8
+ Rake::TestTask.new(:test) do |t|
9
+ t.pattern = 'test/**/*_test.rb'
10
+ t.verbose = true
11
+ end
12
+
13
+ begin
14
+ require 'jeweler'
15
+
16
+ Jeweler::Tasks.new do |gemspec|
17
+ gemspec.name = 'liquidizer'
18
+ gemspec.summary = 'Support for Ruby on Rails views powered by Liquid and loaded from database'
19
+ gemspec.description = <<END
20
+ WIth this gem, you can render your Ruby on Rails views with liquid templates that are loaded from database. This way, the look and feel of your site can be safely configured by it's users.
21
+ END
22
+
23
+ gemspec.email = 'adam.ciganek@gmail.com'
24
+ gemspec.homepage = 'http://github.com/metatribe/liquidizer'
25
+ gemspec.authors = ['Adam Cigánek']
26
+
27
+ gemspec.add_dependency 'liquid', '>= 2.0.0'
28
+ end
29
+
30
+ Jeweler::GemcutterTasks.new
31
+ rescue LoadError
32
+ puts "Jeweler not available. Install it with: gem install jeweler"
33
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,3 @@
1
+ class LiquidTemplate < ActiveRecord::Base
2
+ include Liquidizer::LiquidTemplate
3
+ end
@@ -0,0 +1,219 @@
1
+ require 'liquid'
2
+ require 'liquidizer/support'
3
+
4
+ module Liquidizer
5
+ module ControllerExtensions
6
+ def self.included(base)
7
+ base.class_eval do
8
+ extend ClassMethods
9
+ alias_method_chain :render, :liquid
10
+
11
+ class_inheritable_accessor :liquify_actions
12
+ class_inheritable_hash :liquid_template_names_for_actions
13
+ class_inheritable_accessor :liquid_template_name_for_layout
14
+ end
15
+ end
16
+
17
+ def render_with_liquid(options = {}, &block)
18
+ if action_template = liquid_template_for_action(options)
19
+ assigns = assigns_for_liquify
20
+ content = action_template.render!(assigns)
21
+
22
+ if layout_template = liquid_template_for_layout(options)
23
+ content = layout_template.render!(assigns.merge('content_for_layout' => content))
24
+ options[:layout] = false
25
+ end
26
+
27
+ render_without_liquid(options.merge(:text => content))
28
+ else
29
+ if layout_template = liquid_template_for_layout(options)
30
+ assigns = assigns_for_liquify
31
+
32
+ content = render_to_string(options.merge(:layout => false))
33
+ content = layout_template.render!(assigns.merge('content_for_layout' => content))
34
+
35
+ render_without_liquid(options.merge(:text => content, :layout => false))
36
+ else
37
+ render_without_liquid(options, &block)
38
+ end
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def liquid_template_for_action(options)
45
+ action = extract_action_for_render(options)
46
+
47
+ if action && liquify?(action)
48
+ name = liquid_template_name_for_action(action)
49
+ find_and_parse_liquid_template(name)
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+ def liquify?(action)
56
+ self.class.liquify_actions == :all ||
57
+ self.class.liquify_actions &&
58
+ self.class.liquify_actions.include?(action.to_sym)
59
+ end
60
+
61
+ def liquid_template_for_layout(options)
62
+ if liquify_layout?(options)
63
+ find_and_parse_liquid_template(self.class.liquid_template_name_for_layout)
64
+ else
65
+ nil
66
+ end
67
+ end
68
+
69
+ def liquify_layout?(options)
70
+ if options[:layout] == true ||
71
+ options[:layout].nil? && liquifiable_options?(options)
72
+ self.class.liquid_template_name_for_layout.present?
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ def extract_action_for_render(options)
79
+ if options.nil?
80
+ action_name
81
+ elsif options[:action]
82
+ options[:action]
83
+ elsif liquifiable_options?(options)
84
+ action_name
85
+ else
86
+ nil
87
+ end
88
+ end
89
+
90
+ UNLIQUIFIABLE_OPTIONS = [:partial, :template, :file, :text, :xml, :json, :js, :inline]
91
+
92
+ def liquifiable_options?(options)
93
+ (options.keys.map(&:to_sym) & UNLIQUIFIABLE_OPTIONS).empty?
94
+ end
95
+
96
+ def find_and_parse_liquid_template(name)
97
+ if template_record = find_liquid_template(name)
98
+ template = Liquid::Template.parse(template_record.content)
99
+ prepare_liquid_template(template)
100
+
101
+ template
102
+ else
103
+ nil
104
+ end
105
+ end
106
+
107
+ def liquid_template_name_for_action(action)
108
+ liquid_template_names_for_actions[action.to_sym] || infer_liquid_template_name(action)
109
+ end
110
+
111
+ def infer_liquid_template_name(action)
112
+ "#{controller_path}/#{action}"
113
+ end
114
+
115
+ def find_liquid_template(name)
116
+ current_liquid_templates.find_by_name(name)
117
+ end
118
+
119
+ # This can be overriden to do some nasty things to the template before it's rendered.
120
+ # For example, +assigns+ and +registers+ can be set here. The +template+ is an
121
+ # instance of Liquid::Template.
122
+ def prepare_liquid_template(template)
123
+ end
124
+
125
+ def assigns_for_liquify
126
+ variable_names = instance_variable_names
127
+ variable_names -= protected_instance_variables
128
+
129
+ variable_names.inject({}) do |memo, name|
130
+ assign_name = name[/^@(.*)$/, 1] # strip @
131
+ next memo if assign_name.starts_with?('_') # skip "private" ivars
132
+
133
+ value = instance_variable_get(name)
134
+ value = dropify(value) unless value.respond_to?(:to_liquid)
135
+
136
+ memo[assign_name] = value if value
137
+ memo
138
+ end
139
+ end
140
+
141
+ # Wrap the value in a drop, if it exists. Drop class is infered from the value class:
142
+ #
143
+ # Foo::Bar -> Foo::BarDrop
144
+ def dropify(value)
145
+ drop_class = infer_drop_class(value)
146
+ drop_class && drop_class.new(value)
147
+ end
148
+
149
+ def infer_drop_class(value)
150
+ name = value.class.name + 'Drop'
151
+ name = Liquidizer.drop_module.to_s + '::' + name if Liquidizer.drop_module
152
+
153
+ Support.constant_defined?(name) ? name.constantize : nil
154
+ end
155
+
156
+ module ClassMethods
157
+ # Define actions to liquify (render with liquid templates).
158
+ #
159
+ # == Examples
160
+ #
161
+ # # liquify all actions
162
+ # liquify
163
+ #
164
+ # # also liquify all actions
165
+ # liquify :all
166
+ #
167
+ # # liquify only show and index
168
+ # liquify :show, :index
169
+ #
170
+ # # liquify only edit, but use template called awesome_edit
171
+ # liquify :edit, :as => 'awesome_edit'
172
+ #
173
+ # Unless you specify template name with the :as options, the name will be
174
+ # inferend from controller and action names thusly:
175
+ #
176
+ # controller Blog, action :index - blogs/index
177
+ # controller Blog, action :show - blogs/show
178
+ # controller Blog, action :edit - blogs/edit
179
+ #
180
+ # controller Blog::Post, action :index - blog/posts/index
181
+ # controller Blog::Post, action :show - blog/posts/show
182
+ # controller Blog::Post, action :edit - blog/posts/edit
183
+ #
184
+ # You've got the idea.
185
+ #
186
+ def liquify(*actions)
187
+ options = actions.extract_options!
188
+ actions = actions.map(&:to_sym)
189
+
190
+ self.liquify_actions = actions.empty? ? :all : actions
191
+ self.liquid_template_names_for_actions = {}
192
+
193
+ if options[:as]
194
+ actions.each do |action|
195
+ self.liquid_template_names_for_actions[action] = options[:as]
196
+ end
197
+ end
198
+ end
199
+
200
+ # Liquify the layout.
201
+ #
202
+ # == Examples
203
+ #
204
+ # # Uses layout template "layout"
205
+ # liquify_layout
206
+ #
207
+ # # Uses layout template "wicked_layout"
208
+ # liquify_layout :as => 'wicked_layout'
209
+ #
210
+ def liquify_layout(options = {})
211
+ self.liquid_template_name_for_layout = options[:as] || 'layout'
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ if defined?(ActionController::Base)
218
+ ActionController::Base.send(:include, Liquidizer::ControllerExtensions)
219
+ end
@@ -0,0 +1,23 @@
1
+ module Liquidizer
2
+ module LiquidTemplate
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def find_by_name(name)
9
+ first(:conditions => {:name => name}) || load_default(name)
10
+ end
11
+
12
+ def load_default(name)
13
+ file_name = File.join(Liquidizer.template_path, name) + '.liquid'
14
+
15
+ if File.exist?(file_name)
16
+ new(:name => name, :content => File.read(file_name))
17
+ else
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module Liquidizer
2
+ module MigrationExtensions
3
+ def create_liquid_templates_table
4
+ create_table :liquid_templates do |table|
5
+ table.string :name
6
+ table.text :content
7
+ end
8
+
9
+ add_index :liquid_templates, :name
10
+ end
11
+ end
12
+ end
13
+
14
+ if defined?(ActiveRecord::Migration)
15
+ ActiveRecord::Migration.extend(Liquidizer::MigrationExtensions)
16
+ end
@@ -0,0 +1,17 @@
1
+ module Liquidizer
2
+ module Support
3
+ # This is like Object.const_defined?, but works with namespaced constants (Foo::Bar::Baz).
4
+ def self.constant_defined?(name)
5
+ base = Object
6
+ name.split('::').each do |name|
7
+ if base.const_defined?(name)
8
+ base = base.const_get(name)
9
+ else
10
+ return false
11
+ end
12
+ end
13
+
14
+ true
15
+ end
16
+ end
17
+ end
data/lib/liquidizer.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'liquidizer/controller_extensions'
2
+ require 'liquidizer/migration_extensions'
3
+ require 'liquidizer/liquid_template'
4
+
5
+ module Liquidizer
6
+ # The path the default liquid templates are stored.
7
+ mattr_accessor :template_path
8
+
9
+ # Module for drops. When instance variable is passed to a template, it's wrapped with a drop.
10
+ # This is a module the drops are looked up. If nil, the drops are looked up in the global
11
+ # namespace.
12
+ mattr_accessor :drop_module
13
+
14
+ if defined?(Rails)
15
+ self.template_path = "#{Rails.root}/db/liquid_templates"
16
+ end
17
+ end
@@ -0,0 +1,67 @@
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{liquidizer}
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 = ["Adam Cig\303\241nek"]
12
+ s.date = %q{2010-03-04}
13
+ s.description = %q{WIth this gem, you can render your Ruby on Rails views with liquid templates that are loaded from database. This way, the look and feel of your site can be safely configured by it's users.
14
+ }
15
+ s.email = %q{adam.ciganek@gmail.com}
16
+ s.extra_rdoc_files = [
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "app/models/liquid_template.rb",
25
+ "lib/liquidizer.rb",
26
+ "lib/liquidizer/controller_extensions.rb",
27
+ "lib/liquidizer/liquid_template.rb",
28
+ "lib/liquidizer/migration_extensions.rb",
29
+ "lib/liquidizer/support.rb",
30
+ "liquidizer.gemspec",
31
+ "rails/init.rb",
32
+ "test/controller_extensions_test.rb",
33
+ "test/fixtures/comments/index.html.erb",
34
+ "test/fixtures/posts/index.liquid",
35
+ "test/fixtures/ratings/_stuff.html.erb",
36
+ "test/fixtures/ratings/edit.html.erb",
37
+ "test/fixtures/spams/index.html.erb",
38
+ "test/liquid_template_test.rb",
39
+ "test/support_test.rb",
40
+ "test/test_helper.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/metatribe/liquidizer}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.6}
46
+ s.summary = %q{Support for Ruby on Rails views powered by Liquid and loaded from database}
47
+ s.test_files = [
48
+ "test/support_test.rb",
49
+ "test/liquid_template_test.rb",
50
+ "test/controller_extensions_test.rb",
51
+ "test/test_helper.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
+ s.add_runtime_dependency(%q<liquid>, [">= 2.0.0"])
60
+ else
61
+ s.add_dependency(%q<liquid>, [">= 2.0.0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<liquid>, [">= 2.0.0"])
65
+ end
66
+ end
67
+
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'liquidizer'
@@ -0,0 +1,244 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class BaseController < ActionController::Base
4
+ append_view_path File.dirname(__FILE__) + '/fixtures'
5
+
6
+ private
7
+
8
+ def current_liquid_templates
9
+ LiquidTemplate
10
+ end
11
+ end
12
+
13
+ class PostsController < BaseController
14
+ liquify
15
+
16
+ def index
17
+ @title = 'Hello blog!'
18
+ end
19
+
20
+ def show
21
+ @post = Post.new(:title => 'Liquidizer is awesome!')
22
+ end
23
+
24
+ def update
25
+ render :action => 'edit'
26
+ end
27
+
28
+ def create
29
+ render :status => :created
30
+ end
31
+ end
32
+
33
+ class CommentsController < BaseController
34
+ liquify :show
35
+ liquify :edit, :as => 'funky_comments_edit'
36
+
37
+ def index
38
+ end
39
+
40
+ def show
41
+ end
42
+
43
+ def edit
44
+ end
45
+ end
46
+
47
+ class RatingsController < BaseController
48
+ liquify :show
49
+ liquify_layout
50
+
51
+ def show
52
+ end
53
+
54
+ def edit
55
+ end
56
+
57
+ def new
58
+ render :partial => 'stuff'
59
+ end
60
+
61
+ def create
62
+ render :text => 'create'
63
+ end
64
+ end
65
+
66
+ class SpamsController < BaseController
67
+ def index
68
+ end
69
+ end
70
+
71
+ class Post
72
+ def initialize(attributes = {})
73
+ self.title = attributes[:title]
74
+ end
75
+
76
+ attr_accessor :title
77
+ end
78
+
79
+ class PostDrop < Liquid::Drop
80
+ def initialize(post)
81
+ @post = post
82
+ end
83
+
84
+ def title
85
+ "<em>#{@post.title}</em>"
86
+ end
87
+ end
88
+
89
+ module CoolDrops
90
+ class PostDrop < Liquid::Drop
91
+ def initialize(post)
92
+ @post = post
93
+ end
94
+
95
+ def title
96
+ "<strong>#{@post.title}</strong>"
97
+ end
98
+ end
99
+ end
100
+
101
+ class ControllerExtensionsTest < ActionController::TestCase
102
+ self.controller_class = nil
103
+
104
+ def setup
105
+ LiquidTemplate.destroy_all
106
+ end
107
+
108
+ def teardown
109
+ Liquidizer.drop_module = nil
110
+ end
111
+
112
+ test 'renders with liquid template' do
113
+ setup_controller(PostsController)
114
+
115
+ LiquidTemplate.create!(:name => 'posts/index', :content => "<p>This is liquid template</p>")
116
+
117
+ get :index
118
+ assert_select 'p', 'This is liquid template'
119
+ end
120
+
121
+ test 'passes instance variables to liquid template' do
122
+ setup_controller(PostsController)
123
+
124
+ LiquidTemplate.create!(:name => 'posts/index', :content => "<h1>{{ title }}</h1>")
125
+
126
+ get :index
127
+ assert_select 'h1', /Hello blog!/
128
+ end
129
+
130
+ test 'renders with liquid template when explicit action specified' do
131
+ setup_controller(PostsController)
132
+
133
+ LiquidTemplate.create!(:name => 'posts/edit', :content => "<p>edit post</p>")
134
+ LiquidTemplate.create!(:name => 'posts/update', :content => "<p>update post</p>")
135
+
136
+ get :update
137
+ assert_select 'p', 'edit post'
138
+ end
139
+
140
+ test 'preserves additional render options' do
141
+ setup_controller(PostsController)
142
+
143
+ LiquidTemplate.create!(:name => 'posts/create', :content => "<p>create post</p>")
144
+
145
+ get :create
146
+ assert_response :created
147
+ end
148
+
149
+ test 'does not render with liquid template actions that were not liquified' do
150
+ setup_controller(CommentsController)
151
+
152
+ get :index
153
+ assert_select 'h1', 'This is not liquid template'
154
+ end
155
+
156
+ test 'does not render with liquid if liquify macro not called at all' do
157
+ setup_controller(SpamsController)
158
+
159
+ get :index
160
+ assert_select 'h1', 'This is not liquid template'
161
+ end
162
+
163
+ test 'renders with liquid template with custom name' do
164
+ setup_controller(CommentsController)
165
+
166
+ LiquidTemplate.create!(:name => 'comments/edit', :content => "<p>default edit</p>")
167
+ LiquidTemplate.create!(:name => 'funky_comments_edit', :content => "<p>funky edit</p>")
168
+
169
+ get :edit
170
+ assert_select 'p', 'funky edit'
171
+ end
172
+
173
+ test 'renders liquid template with liquid layout' do
174
+ setup_controller(RatingsController)
175
+
176
+ LiquidTemplate.create!(:name => 'ratings/show', :content => '<p>This is liquid template</p>')
177
+ LiquidTemplate.create!(:name => 'layout',
178
+ :content => '<div id="layout">{{ content_for_layout }}</div>')
179
+
180
+ get :show
181
+ assert_select '#layout p', 'This is liquid template'
182
+ end
183
+
184
+ test 'renders solid template with liquid layout' do
185
+ setup_controller(RatingsController)
186
+
187
+ LiquidTemplate.create!(:name => 'layout',
188
+ :content => '<div id="layout">{{ content_for_layout }}</div>')
189
+
190
+ get :edit
191
+ assert_select '#layout p', 'This is not liquid template'
192
+ end
193
+
194
+ test 'does not apply liquid layout to render :partial' do
195
+ setup_controller(RatingsController)
196
+
197
+ LiquidTemplate.create!(:name => 'layout',
198
+ :content => '<div id="layout">{{ content_for_layout }}</div>')
199
+
200
+ get :new
201
+ assert_select '#layout', false
202
+ end
203
+
204
+ test 'does not apply liquid layout to render :text' do
205
+ setup_controller(RatingsController)
206
+
207
+ LiquidTemplate.create!(:name => 'layout',
208
+ :content => '<div id="layout">{{ content_for_layout }}</div>')
209
+
210
+ get :create
211
+ assert_select '#layout', false
212
+ end
213
+
214
+ test 'dropifies instance variables' do
215
+ setup_controller(PostsController)
216
+
217
+ LiquidTemplate.create!(:name => 'posts/show', :content => '<h1>{{ post.title }}</h1>')
218
+
219
+ get :show
220
+ assert_select 'h1 em', 'Liquidizer is awesome!'
221
+ end
222
+
223
+ test 'dropifies instance variables using namespaced drop' do
224
+ setup_controller(PostsController)
225
+ Liquidizer.drop_module = CoolDrops
226
+
227
+ LiquidTemplate.create!(:name => 'posts/show', :content => '<h1>{{ post.title }}</h1>')
228
+
229
+ get :show
230
+ assert_select 'h1 strong', 'Liquidizer is awesome!'
231
+ end
232
+
233
+ private
234
+
235
+ def setup_controller(controller_class)
236
+ self.class.prepare_controller_class(controller_class)
237
+
238
+ # This is copied over from ActionController::TestCase.setup_controller_request_and_response
239
+ @controller = controller_class.new
240
+ @controller.request = @request
241
+ @controller.params = {}
242
+ @controller.send(:initialize_current_url)
243
+ end
244
+ end
@@ -0,0 +1 @@
1
+ <h1>This is not liquid template</h1>
@@ -0,0 +1,3 @@
1
+ <h1>Hello world</h1>
2
+
3
+ <p>This is a liquid template.</p>
@@ -0,0 +1 @@
1
+ Stuff
@@ -0,0 +1 @@
1
+ <p>This is not liquid template</p>
@@ -0,0 +1 @@
1
+ <h1>This is not liquid template</h1>
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class LiquidTemplateTest < ActiveSupport::TestCase
4
+ def setup
5
+ LiquidTemplate.delete_all
6
+ end
7
+
8
+ test 'find_by_name finds template by name if it exists' do
9
+ one = LiquidTemplate.create!(:name => 'posts/index')
10
+ two = LiquidTemplate.create!(:name => 'posts/show')
11
+
12
+ assert_equal one, LiquidTemplate.find_by_name('posts/index')
13
+ end
14
+
15
+ test 'find_by_name fallbacks to default template' do
16
+ expected_content = File.read(File.dirname(__FILE__) + '/fixtures/posts/index.liquid')
17
+ found = LiquidTemplate.find_by_name('posts/index')
18
+
19
+ assert_equal expected_content, found.content
20
+ end
21
+
22
+ test 'find_by_name returns nil if not even default template exists' do
23
+ assert_nil LiquidTemplate.find_by_name('ninjas!')
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ module Foo
4
+ class Bar
5
+ end
6
+
7
+ class Awesomeness
8
+ end
9
+ end
10
+
11
+ class Bar
12
+ end
13
+
14
+ class SupportTest < ActiveSupport::TestCase
15
+ test 'constant_defined? with non-namespaced constant' do
16
+ assert Liquidizer::Support.constant_defined?('Bar')
17
+ assert !Liquidizer::Support.constant_defined?('Baz')
18
+ end
19
+
20
+ test 'constant_defined? with namespaced constant' do
21
+ assert Liquidizer::Support.constant_defined?('Foo::Bar')
22
+ assert !Liquidizer::Support.constant_defined?('Foo::Baz')
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'action_controller'
4
+ require 'active_record'
5
+ require 'active_support/test_case'
6
+
7
+ $: << File.dirname(__FILE__) + '/../lib'
8
+ $: << File.dirname(__FILE__) + '/../app/models'
9
+
10
+ require 'liquidizer'
11
+ require 'liquid_template'
12
+
13
+ Liquidizer.template_path = File.dirname(__FILE__) + '/fixtures'
14
+
15
+ # Establish a temporary sqlite3 db for testing.
16
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
17
+ ActiveRecord::Base.logger # instantiate logger
18
+ ActiveRecord::Schema.define(:version => 1) do
19
+ create_liquid_templates_table
20
+ end
21
+
22
+ ActionController::Routing::Routes.draw do |map|
23
+ map.connect ':controller/:action/:id'
24
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liquidizer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - "Adam Cig\xC3\xA1nek"
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-04 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: liquid
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 0
30
+ - 0
31
+ version: 2.0.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: |
35
+ WIth this gem, you can render your Ruby on Rails views with liquid templates that are loaded from database. This way, the look and feel of your site can be safely configured by it's users.
36
+
37
+ email: adam.ciganek@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - README.rdoc
44
+ files:
45
+ - .gitignore
46
+ - README.rdoc
47
+ - Rakefile
48
+ - VERSION
49
+ - app/models/liquid_template.rb
50
+ - lib/liquidizer.rb
51
+ - lib/liquidizer/controller_extensions.rb
52
+ - lib/liquidizer/liquid_template.rb
53
+ - lib/liquidizer/migration_extensions.rb
54
+ - lib/liquidizer/support.rb
55
+ - liquidizer.gemspec
56
+ - rails/init.rb
57
+ - test/controller_extensions_test.rb
58
+ - test/fixtures/comments/index.html.erb
59
+ - test/fixtures/posts/index.liquid
60
+ - test/fixtures/ratings/_stuff.html.erb
61
+ - test/fixtures/ratings/edit.html.erb
62
+ - test/fixtures/spams/index.html.erb
63
+ - test/liquid_template_test.rb
64
+ - test/support_test.rb
65
+ - test/test_helper.rb
66
+ has_rdoc: true
67
+ homepage: http://github.com/metatribe/liquidizer
68
+ licenses: []
69
+
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --charset=UTF-8
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ requirements: []
90
+
91
+ rubyforge_project:
92
+ rubygems_version: 1.3.6
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Support for Ruby on Rails views powered by Liquid and loaded from database
96
+ test_files:
97
+ - test/support_test.rb
98
+ - test/liquid_template_test.rb
99
+ - test/controller_extensions_test.rb
100
+ - test/test_helper.rb