merge blog features that got deleted when repo was renamed.
[leap_website.git] / lib / property_set.rb
1 #
2 # holds the set or properties defined for each static page.
3 # property sets are organized by locale.
4 #
5 # e.g.
6 #
7 # setting the property (in en.haml):
8 #
9 #   - @title = 'hi'
10 #
11 # getting the property
12 #
13 #   page.props.title
14 #
15
16 require 'i18n'
17 require 'time'
18 require 'rubygems'
19 require 'haml'
20 require 'RedCloth'
21
22 class PropertySet
23
24   DEFAULT_LOCALE = 'en'
25
26   #
27   # a simple class to pass through all member variables as attributes.
28   # when the template for a page is evaluated, all the member variabled defined in that template
29   # are loaded as member variables of the AttrObject instance.
30   #
31   class AttrObject
32     def initialize(property_set, locale)
33       @_ps = property_set
34       @_locale = locale
35     end
36     def method_missing(method)
37       get(method)
38     end
39     def textile(str)
40       RedCloth.new(str).to_html
41     end
42     def get(var_name)
43       value = instance_variable_get("@#{var_name}")
44       if value.nil?
45         if @_locale != DEFAULT_LOCALE
46           # try value from default locale
47           @_ps.get_var(var_name)
48         else
49           # try inherited value
50           @_ps.get_inherited_var(var_name, @_locale)
51         end
52       else
53         value
54       end
55     end
56     def set(var_name, value)
57       instance_variable_set("@#{var_name}", value)
58     end
59   end
60
61   def initialize(page=nil)
62     @page = page
63     @locales = {}
64   end
65
66   #
67   # evaluate the template_string, and load the variables defined into an AttrObject.
68   #
69   def eval(locale, template_string)
70     # render to the template to get the instance variables
71     attrs = AttrObject.new(self, locale)
72     begin
73       # template is evaluated with binding of attrs object
74       Haml::Engine.new(template_string, :format => :html5).render(attrs)
75     rescue Exception => exc
76       # eat exceptions
77     end
78
79     # convert date/time variables to objects of class Time
80     attrs.instance_variables.grep(/_at$/).each do |time_variable|
81       attrs.instance_variable_set(time_variable, Time.parse(attrs.instance_variable_get(time_variable)))
82     end
83
84     # save the AttrObject
85     @locales[locale] = attrs
86   end
87
88   #
89   # ALTERNATE EVAL
90   #
91   # body = nil
92   # controller = ApplicationController.new()
93   # controller.response = ActionController::Response.new()
94   # view = ActionView::Base.new(["#{Rails.root}/app/views/pages","#{Rails.root}/app/views"], {}, controller)
95   # view.extend ApplicationHelper  # TODO: figure out how to extend all helpers
96   # view.extend BlogHelper
97   # view.extend HamlHelper
98   # view.extend NavigationHelper
99   # begin
100   #   body = Haml::Engine.new(template_string, :format => :html5).render(view)  # template is evaluated with binding of view object
101   # rescue Exception => exc
102   #   # eat exceptions
103   # end
104   #
105   # this doesn't work because view doesn't get instance variables set
106   #
107   # copy new instance variables
108   # new_variables = view.instance_variables
109   # new_variables = original_instance_variables - view.instance_variables
110   # new_variables.each do |variable|
111   #   #attrs.instance_variable_set(variable, view.instance_variable_get(variable))
112   # end
113   #
114   # clean up attrs
115   # attrs.instance_variable_set('@body', body)
116   #
117
118   #
119   # allows property_set.propname shortcut, assumes default locale
120   #
121   def method_missing(method)
122     get_var(method)
123   end
124
125   def locale(l)
126     @locales[l.to_s] || @locales[DEFAULT_LOCALE]
127   end
128
129   def get_var(var_name, locale=I18n.locale)
130     attrs = locale(locale)
131     if attrs
132       attrs.get(var_name)
133     else
134       nil
135     end
136   end
137
138   #
139   # tries to get the value of an inherited variable
140   #
141   def get_inherited_var(var_name, locale=I18n.locale)
142     if @page && @page.parent && @page.parent.props
143       @page.parent.props.get_var(var_name, locale)
144     end
145   end
146 end
147
148 #
149 # a simple little test.
150 #
151 if ARGV.grep('--test').any?
152   text_en = "
153 - @title = 'hi'
154 - @author = 'you'
155 - @created_at = 'Sun Aug 12 18:32:20 PDT 2012'
156 - ignored = 1
157 this is the body"
158
159   text_es = "
160 - @title = 'hola'
161 - @author = 'tu'
162 - @heading = textile 'h1. hi'
163 "
164
165   ps = PropertySet.new
166   ps.eval('en', text_en)
167   ps.eval('es', text_es)
168
169   p ps.title == 'hi'
170   p ps.locale(:es).title == 'hola'
171   p ps.locale(:es).created_at == Time.parse('Sun Aug 12 18:32:20 PDT 2012')
172   p ps.ignored == nil
173   p ps.locale(:es).heading == "<h1>hi</h1>"
174   p ps.body == "this is the body\n"
175 end