Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/dynamic_liquid_templates.rb | 148 | 76 | 100.00%
|
100.00%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 module DynamicLiquidTemplates |
2 # Renders using Liquid as the template engine and reloads the templates from the |
3 # database instead of files. |
4 # |
5 # * <tt>:collection</tt> - the name of the collection array (convention: controller name) |
6 # * <tt>:object</tt> - the name of the single model object (convention: model name) |
7 # * <tt>:layout</tt> - name of the layout template (convention: controller_name) |
8 # * <tt>:controller</tt> - if you're not following the naming conventions you can |
9 # override the controller name |
10 # * <tt>:action</tt> - if you're not following the naming conventions you can override |
11 # the action name |
12 # * <tt>:dynamic_template_class</tt> - name of the model that searches the correct Liquid |
13 # template (default: DynamicTemplate) |
14 # |
15 # == Dynamic Template |
16 # |
17 # This will only work if there is a proper model that handles retrieving Liquid templates from the |
18 # database. The minimal schema is to have a string 'path' column and a text 'body' column. Paths |
19 # will be such as 'posts/show', 'posts/index' or 'layouts/posts'. |
20 # |
21 # == Overrides |
22 # |
23 # This method expects to find a 'parent' method defined in the controller that returns the |
24 # parent model object in case this is a nested controller |
25 # |
26 # == Returns |
27 # |
28 # It will correctly assign needed instance variables to Liquid. It will also modify the |
29 # model class to add +show_path+ and +edit_path+ caches to be called within the Liquid |
30 # template. It also supports one level nested resource named routes. |
31 # |
32 # This way, the only need you have to do in your controller, if it follows normal |
33 # conventions is to add this method to the 'format.html' call within the 'respond_to' |
34 # block, and it will do everything necessary |
35 # |
36 # You will also receive the usually expected 'posts' and 'post' named variables, |
37 # following your controller name. It will also create 'collection' and 'object' so you |
38 # can make your templates more generic. And if you have defined the 'parent' method in |
39 # your controller you will also get a 'parent' drop in your template. |
40 # |
41 # == Requirements |
42 # |
43 # Don't forget to add the Liquid gem to your environment.rb file: |
44 # |
45 # config.gem "tobi-liquid", :lib => "liquid", :source => "http://gems.github.com" |
46 # |
47 def render_with_dynamic_liquid(assigns = {}) |
48 _controller_name = assigns.delete(:controller) || self.controller_name |
49 _model_name = _controller_name.singularize |
50 _collection_variable_name = (assigns.delete(:collection) || "@#{_controller_name}").to_s # @comments |
51 _object_variable_name = (assigns.delete(:object) || "@#{_model_name}").to_s # @comment |
52 _parent_name = respond_to?(:parent) ? "#{parent.class.name.underscore}_" : nil |
53 _namespace = assigns.include?(:namespace) ? "#{assigns[:namespace]}_" : nil |
54 |
55 instance_variables.each do |variable| |
56 # discovers variables and path for index action |
57 case variable |
58 when _collection_variable_name: |
59 assigns.merge!( "collection" => instance_variable_get(variable) ) |
60 assigns.merge!( _controller_name => instance_variable_get(variable) ) |
61 # discovers variables for all the other actions |
62 when _object_variable_name: |
63 # post_comment_path(@post, @comment) or comment_path(@comment) |
64 _object_named_route = "#{_namespace}#{_parent_name}#{_model_name}_path(#{_parent_name ? 'parent, ' : nil}instance_variable_get(variable))" |
65 |
66 assigns.merge!( "object_path" => eval(_object_named_route) ) rescue nil |
67 assigns.merge!( "object" => instance_variable_get(variable) ) |
68 assigns.merge!( _model_name => instance_variable_get(variable) ) |
69 end |
70 end |
71 |
72 # if this is a nested resource, override the 'parent' method to return the parent object |
73 if _parent_name |
74 # posts_path(@post) |
75 assigns.merge!( "parent" => parent ) |
76 assigns.merge!( "parent_path" => eval("#{_namespace}#{_parent_name}path(#{_parent_name ? 'parent' : nil})") ) rescue nil |
77 end |
78 |
79 # post_comments_path(@posts), new_post_comment_path(@posts) |
80 # comments_path, new_comment_path |
81 _collection_named_route = "#{_namespace}#{_parent_name}#{_controller_name}_path(#{_parent_name ? 'parent' : nil})" |
82 _new_named_route = "new_#{_namespace}#{_parent_name}#{_model_name}_path(#{_parent_name ? 'parent' : nil})" |
83 |
84 assigns.merge!( "collection_path" => eval(_collection_named_route) ) rescue nil |
85 assigns.merge!( "new_object_path" => eval(_new_named_route) ) rescue nil |
86 |
87 if assigns["object"] && assigns["object"].id && !assigns["collection"] |
88 assigns.merge!("collection" => [assigns["object"]]) |
89 end |
90 |
91 _object = assigns["collection"].try(:first) |
92 _object_name = if _object |
93 # create attributes to cache resource paths |
94 unless _object.respond_to?(:_show_path) |
95 _object.class.class_eval do |
96 attr_accessor :_show_path |
97 attr_accessor :_edit_path |
98 end |
99 end |
100 # override liquid serializer to add the cached resource paths |
101 if _object.respond_to?(:to_liquid) && !_object.respond_to?(:to_liquid_old) |
102 _object.class.class_eval do |
103 alias :to_liquid_old :to_liquid |
104 def to_liquid |
105 to_liquid_old.merge( |
106 'show_path' => self._show_path, |
107 'edit_path' => self._edit_path ) |
108 end |
109 end |
110 end |
111 _object.class.name.underscore |
112 end |
113 |
114 # cache each model named_route into itself |
115 if assigns["collection"] |
116 assigns["collection"].each do |_object| |
117 # post_comment_path(parent, @comment), edit_post_comment_path(parent, @comment) |
118 # comment_path(@comment), edit_comment_path(@comment) |
119 _show_path = "#{_namespace}#{_parent_name}#{_object_name}_path(#{_parent_name ? 'parent, ' : nil}_object)" |
120 _edit_path = "edit_#{_namespace}#{_parent_name}#{_object_name}_path(#{_parent_name ? 'parent, ' : nil}_object)" |
121 |
122 _object._show_path = eval(_show_path) |
123 _object._edit_path = eval(_edit_path) |
124 end |
125 end |
126 |
127 assigns.merge!("form_authenticity_token" => form_authenticity_token) |
128 |
129 # begin Liquid rendering procedure |
130 _dynamic_template_klass = assigns.delete(:dynamic_template_class) || DynamicTemplate |
131 |
132 _namespace_dir = assigns.include?(:namespace) ? "#{assigns.delete(:namespace)}/" : nil |
133 _layout_path = assigns.delete(:layout) || "layouts/#{_namespace_dir}#{_controller_name}" |
134 _template_path = "#{_namespace_dir}#{_controller_name}/#{assigns.delete(:action) || self.action_name}" |
135 _layout = Liquid::Template.parse(_dynamic_template_klass.find_by_path(_layout_path).body) |
136 _template = Liquid::Template.parse(_dynamic_template_klass.find_by_path(_template_path).body) |
137 |
138 options = { :filters => [master_helper_module], :registers => { |
139 :action_view => ActionView::Base.new([], {}, self), |
140 :controller => self |
141 } } |
142 _rend_temp = _template.render(assigns, options) |
143 _rend_layout = _layout.render({'content_for_layout' => _rend_temp}, options) |
144 |
145 headers["Content-Type"] ||= 'text/html; charset=utf-8' |
146 render :text => _rend_layout |
147 end |
148 end |
Generated on Tue Sep 08 00:18:32 -0300 2009 with rcov 0.9.0