glue 0.31.0 → 0.40.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.
Files changed (46) hide show
  1. data/doc/AUTHORS +1 -1
  2. data/doc/LICENSE +2 -3
  3. data/doc/RELEASES +0 -4
  4. data/lib/glue.rb +3 -3
  5. data/lib/glue/attribute.rb +114 -0
  6. data/lib/glue/attributeutils.rb +117 -0
  7. data/lib/glue/autoreload.rb +0 -4
  8. data/lib/glue/builder.rb +0 -2
  9. data/lib/glue/builder/xml.rb +0 -2
  10. data/lib/glue/cache.rb +3 -5
  11. data/lib/glue/cache/drb.rb +0 -2
  12. data/lib/glue/cache/memory.rb +0 -2
  13. data/lib/glue/cache/og.rb +11 -6
  14. data/lib/glue/configuration.rb +60 -15
  15. data/lib/glue/fixture.rb +3 -5
  16. data/lib/glue/localization.rb +0 -2
  17. data/lib/glue/logger.rb +1 -2
  18. data/lib/glue/mail.rb +0 -2
  19. data/lib/glue/mailer.rb +4 -2
  20. data/lib/glue/mailer/incoming.rb +0 -2
  21. data/lib/glue/mailer/outgoing.rb +3 -5
  22. data/lib/glue/settings.rb +0 -2
  23. data/lib/glue/uri.rb +0 -2
  24. data/lib/glue/validation.rb +6 -8
  25. data/test/glue/builder/tc_xml.rb +3 -2
  26. data/test/glue/tc_attribute.rb +112 -0
  27. data/test/glue/{tc_property_mixins.rb → tc_attribute_mixins.rb} +9 -11
  28. data/test/glue/tc_configuration.rb +1 -1
  29. data/test/glue/tc_fixture.rb +4 -3
  30. data/test/glue/tc_logger.rb +2 -2
  31. data/test/glue/tc_mail.rb +22 -21
  32. data/test/glue/tc_stores.rb +0 -2
  33. data/test/glue/tc_uri.rb +12 -12
  34. data/test/glue/tc_validation.rb +13 -13
  35. metadata +52 -64
  36. data/INSTALL +0 -56
  37. data/ProjectInfo +0 -49
  38. data/README +0 -21
  39. data/lib/glue/markup.rb +0 -123
  40. data/lib/glue/property.rb +0 -290
  41. data/lib/glue/sanitize.rb +0 -48
  42. data/lib/glue/template.rb +0 -219
  43. data/setup.rb +0 -1585
  44. data/test/glue/tc_property.rb +0 -112
  45. data/test/glue/tc_property_type_checking.rb +0 -41
  46. data/test/glue/tc_template.rb +0 -35
data/lib/glue/property.rb DELETED
@@ -1,290 +0,0 @@
1
- require 'facet/annotation'
2
- require 'facet/inheritor'
3
- require 'facet/dictionary'
4
- require 'facets/core/module/on_included'
5
- require 'facets/more/aspects'
6
-
7
- require 'glue/validation'
8
- require 'og/entity'
9
- require 'og/relation/all'
10
-
11
- # A convienience structure that holds property
12
- # metadata. A property is a special type of class annotation.
13
- # Typically used in Og managed classes (ie Entities), but it
14
- # is *not* Og specific.
15
- #--
16
- # TODO: reimplement type checking.
17
- # TODO: try to clean this up.
18
- #++
19
-
20
- class Property
21
-
22
- # The hash used to store the property options.
23
-
24
- attr_accessor :hash
25
-
26
- def initialize(hash)
27
- @hash = hash
28
- @hash = @hash.to_h unless @hash.is_a?(Hash)
29
- end
30
-
31
- def [](key)
32
- @hash[key]
33
- end
34
- alias_method :method_missing, :[]
35
-
36
- def []=(key, val)
37
- @hash[key] = val
38
- end
39
-
40
- def <=>(other)
41
- @hash[:symbol] <=> other.hash[:symbol]
42
- end
43
-
44
- def to_s
45
- @hash[:symbol].to_s
46
- end
47
- alias_method :name, :to_s
48
-
49
- # :section: Property related utils and helpers.
50
-
51
- class << self
52
-
53
- # Populate an object from a hash of values.
54
- # This is a truly dangerous method.
55
- #
56
- # === Options:
57
- # * name
58
- # * force_boolean
59
-
60
- def populate_object(obj, values, options = {})
61
- # If a class is passed create an instance.
62
- obj = obj.new if obj.is_a?(Class)
63
-
64
- for prop in obj.class.properties.values
65
-
66
- unless options[:all]
67
- next if prop.symbol == obj.class.primary_key.symbol or prop.control == :none or prop.disable_control
68
- end
69
-
70
- prop_name = prop.symbol.to_s
71
-
72
- # See if there is an incoming request param for this prop.
73
-
74
- if values.has_key?(prop_name)
75
-
76
- prop_value = values[prop_name]
77
-
78
- # to_s must be called on the prop_value incase the
79
- # request is IOString.
80
-
81
- prop_value = prop_value.to_s unless prop_value.is_a?(Hash) or prop_value.is_a?(Array)
82
-
83
- # If property is a Blob dont overwrite current
84
- # property's data if "".
85
-
86
- break if prop.klass == Og::Blob and prop_value.empty?
87
-
88
- # If custom preprocessing is active then try and
89
- # preprocess.
90
-
91
- prop_value = preprocess_value(obj, prop, prop_value) if options[:preprocess]
92
-
93
- # assign using __force_ methods.
94
- obj.send("__force_#{prop_name}", prop_value)
95
-
96
- # Set a boolean property to false if it is not in the request.
97
- # requires force_boolean == true.
98
-
99
- elsif options[:force_boolean] and (prop.klass == TrueClass or prop.klass == FalseClass)
100
- obj.send("__force_#{prop_name}", 0)
101
- end
102
- end
103
-
104
- if options[:assign_relations]
105
- for rel in obj.class.relations
106
-
107
- unless options[:all]
108
- next if rel.options[:control] == :none or rel.options[:disable_control]
109
- end
110
-
111
- rel_name = rel.name.to_s
112
-
113
- # Renew the relations from values
114
-
115
- if rel.kind_of?(Og::RefersTo)
116
- if foreign_oid = values[rel_name]
117
- foreign_oid = foreign_oid.to_s unless foreign_oid.is_a?(Hash) or foreign_oid.is_a?(Array)
118
- foreign_oid = nil if foreign_oid == 'nil' or foreign_oid == 'none'
119
- # if custom preprocessing is active then try and preprocess
120
- foreign_oid = preprocess_value(obj, rel, foreign_oid) if options[:preprocess]
121
- end
122
- obj.send("__force_#{rel.foreign_key}", foreign_oid)
123
- elsif rel.kind_of?(Og::JoinsMany) || rel.kind_of?(Og::HasMany)
124
- collection = obj.send(rel_name)
125
- collection.remove_all
126
- if values.has_key?(rel_name)
127
- primary_keys = values[rel_name]
128
-
129
- # if custom preprocessing is active then try and preprocess
130
- primary_keys = preprocess_value(obj, rel, primary_keys) if options[:preprocess]
131
-
132
- primary_keys.each do |v|
133
- next if v.to_s == "nil" or v.to_s == "none"
134
- collection << rel.target_class[v.to_s.to_i]
135
- end
136
- end
137
- end
138
- end
139
- end
140
-
141
- #--
142
- # gmosx, FIXME: this is a hack, will be replaced with proper
143
- # code soon.
144
- #++
145
-
146
- for callback in obj.class.assign_callbacks
147
- callback.call(obj, values, options)
148
- end if obj.class.respond_to?(:assign_callbacks)
149
-
150
- return obj
151
- end
152
-
153
- # This method will attempt to process [value] through the
154
- # any on_populate preprocessors available.
155
- #
156
- # first looks if a method was specified on the property
157
- #
158
- # ie. property :this, String, :on_populate => :change_value
159
- # ==> would mean #change_value(val) would get called
160
- # TODO: set :on_populate to false to exclude it from any preprocessing
161
- #
162
- # next an #on_populate method will be looked for on any
163
- # associated Nitro::Control (if controls is running)
164
- #
165
- # otherwise [value] is left untouched
166
-
167
- def preprocess_value(obj, prop_or_rel, value)
168
- if prop_or_rel.on_populate && obj.respond_to?(prop_or_rel.on_populate.to_sym)
169
- return obj.send(prop_or_rel.on_populate.to_sym, value)
170
- elsif Object.const_defined? :Nitro
171
- if control = Nitro::Form::Control.fetch(obj, prop_or_rel, :default => nil) and control.respond_to?(:on_populate)
172
- return control.on_populate(value)
173
- end
174
- else
175
- return value
176
- end
177
- end
178
-
179
- def eval_helpers(writer, m, sym, klass)
180
- return unless writer
181
-
182
- code = %{
183
- def __force_#{sym}(val)
184
- if respond_to?(:force_#{sym})
185
- self.#{sym} = force_#{sym}(val)
186
- else
187
- self.#{sym}=(} << case klass.name
188
- when Fixnum.name: 'val.to_s.empty? ? nil : val.to_i'
189
- when String.name: 'val.to_s'
190
- when Float.name: 'val.to_f'
191
- when Time.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"],val["hour"],val["min"]) : Time.parse(val.to_s)'
192
- when Date.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"]).to_date : Time.parse(val.to_s).to_date'
193
- when TrueClass.name, FalseClass.name: 'val == "on" or val == "true" ? true: val.to_i > 0'
194
- else 'val'
195
- end + %{)
196
- end
197
- end
198
- }
199
-
200
- m.module_eval(code)
201
- end
202
-
203
- end
204
- end
205
-
206
- #--
207
- # Extend the default Module.
208
- #
209
- # The properties hash, keeps the property metadata as a hash to avoid
210
- # the null issue.
211
- #++
212
-
213
- class Module
214
- [ nil, :_reader, :_writer, :_accessor].each do |m|
215
- writer = (m != :reader)
216
- code = %{
217
- def prop#{m} (*args)
218
- inheritor(:properties, Dictionary.new, :merge) unless @properties
219
-
220
- args = args.flatten
221
- harg = {}
222
- while args.last.is_a?(Hash)
223
- harg.update(args.pop)
224
- end
225
-
226
- harg[:klass] = args.pop if args.last.is_a?(Class)
227
- klass = harg[:klass] ||= String
228
-
229
- raise if args.empty? and harg.empty?
230
-
231
- # If the class defines the include_as_property callback
232
- # call to modify the base with custom code.
233
-
234
- skip = false
235
-
236
- if klass.respond_to? :included_as_property
237
- skip = klass.included_as_property(self, args, harg)
238
- end
239
-
240
- unless skip
241
- if !args.empty?
242
- undef_keys = args.select{ |a| !method_defined?(a) }
243
- unless undef_keys.empty?
244
- attr#{m} *undef_keys
245
- end
246
- args.each { |a|
247
- a = a.to_sym
248
- an = define_annotation(a, harg)
249
- ah = an.to_h.merge(:symbol => a)
250
- # gmosx: allow for duplicate declarations.
251
- properties![a] = Property.new(ah)
252
- Property.eval_helpers(#{writer}, self, a, harg[:klass])
253
- }
254
- else
255
- undef_keys = harg.keys.select{ |a| !method_defined?(a) }
256
- attribute#{m} *undef_keys
257
- harg.each { |a,h|
258
- a = a.to_sym
259
- an = define_annotation(a, h)
260
- ah = an.to_h.merge(:symbol => a)
261
- # gmosx: allow for property redefinitions.
262
- properties![a] = Property.new(ah)
263
- Property.eval_helpers(#{writer}, self, a, harg[:klass])
264
- }
265
- end
266
- end
267
-
268
- Module.__add_prop_hook__(self)
269
- end
270
- }
271
-
272
- module_eval(code)
273
- end
274
- alias :property :prop_accessor
275
-
276
- # NITRO specific!! leave blank in facets.
277
- # TODO: factor in eval_helpers into the hook!
278
-
279
- def self.__add_prop_hook__(m)
280
- m.send(:include, Og::EntityMixin) unless m.ancestors.include?(Og::EntityMixin)
281
- m.send(:include, Glue::Validation) unless m.ancestors.include?(Glue::Validation)
282
- m.send(:include, ::Aspects) unless m.ancestors.include?(::Aspects)
283
- end
284
-
285
- end
286
-
287
- # * George Moschovitis <gm@navel.gr>
288
- # * Tom Sawyer <transfire@gmail.com>
289
- # * Chris Farmiloe <chris.farmiloe@farmiloe.com>
290
- # * Bryan Soto <bryan.a.soto@gmail.com>
data/lib/glue/sanitize.rb DELETED
@@ -1,48 +0,0 @@
1
- # Code from rubyonrails project (http://www.rubyonrails.com)
2
- # Temporarily here.
3
-
4
- require 'html/tokenizer'
5
- require 'html/node'
6
-
7
- VERBOTEN_TAGS = %w(form script) unless defined?(VERBOTEN_TAGS)
8
- VERBOTEN_ATTRS = /^on/i unless defined?(VERBOTEN_ATTRS)
9
-
10
- class String
11
- # Sanitizes the given HTML by making form and script tags into regular
12
- # text, and removing all "onxxx" attributes (so that arbitrary Javascript
13
- # cannot be executed). Also removes href attributes that start with
14
- # "javascript:".
15
- #
16
- # Returns the sanitized text.
17
- def self.sanitize(html)
18
- # only do this if absolutely necessary
19
- if html.index("<")
20
- tokenizer = HTML::Tokenizer.new(html)
21
- new_text = ""
22
-
23
- while token = tokenizer.next
24
- node = HTML::Node.parse(nil, 0, 0, token, false)
25
- new_text << case node
26
- when HTML::Tag
27
- if VERBOTEN_TAGS.include?(node.name)
28
- node.to_s.gsub(/</, "&lt;")
29
- else
30
- if node.closing != :close
31
- node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS }
32
- if node.attributes["href"] =~ /^javascript:/i
33
- node.attributes.delete "href"
34
- end
35
- end
36
- node.to_s
37
- end
38
- else
39
- node.to_s.gsub(/</, "&lt;")
40
- end
41
- end
42
-
43
- html = new_text
44
- end
45
-
46
- html
47
- end
48
- end
data/lib/glue/template.rb DELETED
@@ -1,219 +0,0 @@
1
- require 'facets/more/openobject'
2
- require 'glue/configuration'
3
-
4
- module Glue
5
-
6
- # A template is a text file with embeded Ruby code. The template
7
- # processor converts the original text file to ruby code and
8
- # then evaluates this code to produce the result of the
9
- # template transformation.
10
-
11
- module TemplateMixin
12
-
13
- # Convert a template to actual Ruby code, ready to be
14
- # evaluated.
15
- #
16
- # [+template+]
17
- # The template as a String.
18
- #
19
- # [+buffer+]
20
- # The variable to act as a buffer where the ruby code
21
- # for this template will be generated. Passed as a
22
- # String.
23
- #
24
- # [+base_dir+]
25
- # The base directory where the templates reside.
26
-
27
- def compile_template(template, buffer = '@out', base_dir = Dir.pwd)
28
- text = template.dup
29
-
30
- # Strip the xml header! (interracts with the following gsub!)
31
- text.gsub!(/<\?xml.*\?>/, "")
32
-
33
- # Statically include sub-template files.
34
- # The target file is included at compile time.
35
- #
36
- # gmosx: must be xformed before the <?r pi.
37
- #
38
- # Example:
39
- # <?include href="root/myfile.sx" ?>
40
-
41
- text.gsub!(/<\?include href=["|'](.*?)["|'](.*)\?>/) do |match|
42
- itext = File.read("#{base_dir}/#$1")
43
- itext.gsub!(/<\?xml.*\?>/, '')
44
- itext.gsub!(/<\/?root(.*?)>/m, ' ');
45
- itext
46
- end
47
-
48
- # Transform include instructions <include href="xxx" />
49
- # must be transformed before the processinc instructions.
50
- # Useful to include fragments cached on disk
51
- #
52
- # gmosx, FIXME: NOT TESTED! test and add caching.
53
- # add load_statically_included fixes.
54
-
55
- text.gsub!(/<include href=["|'](.*?)["|'](.*)(.?)\/>/) do |match|
56
- "<?r File.read( '\#{@dispatcher.root}/#$1' ?>"
57
- end
58
-
59
- # xform render/inject instructions <render href="xxx" />
60
- # must be transformed before the processinc instructions.
61
-
62
- text.gsub!(/<(render|inject) href=["|'](.*?)["|'](.*)(.?)\/>/) do |match|
63
- "<?r render '#$2' ?>"
64
- end
65
-
66
- # Remove <root> elements. typically removed by xslt but lets
67
- # play it safe. The <root> element is typically added to
68
- # template files to make them XHTML valid.
69
-
70
- text.gsub!(/<(\/)?root>/, '')
71
-
72
- # Transform the processing instructions, use <?r as
73
- # a marker.
74
-
75
- text.gsub!(/\?>/, "; #{buffer} << %^")
76
- text.gsub!(/<\?r(\s?)/, "^; ")
77
-
78
- # Transform alternative code tags.
79
- # (very useful in xsl stylesheets)
80
-
81
- text.gsub!(/<\/ruby>/, "; #{buffer} << %^")
82
- text.gsub!(/<ruby>/, "^; ")
83
-
84
- # Also handle erb/asp/jsp style tags. Those tags
85
- # *cannot* be used with an xslt stylesheet.
86
-
87
- text.gsub!(/%>/, "; #{buffer} << %^")
88
- text.gsub!(/<%/, "^; ")
89
-
90
- # Alterative versions of interpolation.
91
- # (very useful in xsl stylesheets)
92
- # Example: #\my_val\
93
-
94
- text.gsub!(/\#\\(.*?)\\/, '#{\1}')
95
-
96
- # Alternative for entities.
97
- # (useful in xsl stylesheets)
98
- # Examples: %nbsp;, %rquo;
99
-
100
- text.gsub!(/%(#\d+|\w+);/, '&\1;')
101
-
102
- # Compile time ruby code. This code is evaluated when
103
- # compiling the template and the result injected directly
104
- # into the result. Usefull for example to prevaluate
105
- # localization. Just use the #[] marker instead of #{}.
106
-
107
- text.gsub!(/\#\[(.*?)\]/) do |match|
108
- eval($1)
109
- end
110
-
111
- text = "#{buffer} << %^" + text + "^"
112
-
113
- return text
114
- end
115
-
116
- # Evaluate the template.
117
- #
118
- # [+ruby+]
119
- # A String containing the compiled template
120
- # code.
121
- #
122
- # [+binding+]
123
- # The evaluation binding for the rendering.
124
-
125
- def evaluate_template(ruby, the_binding = nil)
126
- eval(ruby, the_binding)
127
- end
128
-
129
- # Compile and render the template.
130
-
131
- def process_template(template, buffer = '@out', the_binding = nil)
132
- evaluate_template(compile_template(template, buffer), the_binding)
133
- end
134
-
135
- end
136
-
137
- # A helper class that provides access to the Template methods
138
- # as singleton methods.
139
-
140
- class Template
141
-
142
- # The default root directory where template files reside.
143
-
144
- if File.exist?('template')
145
- default_root = 'template'
146
- elsif File.exist?('src/template')
147
- default_root = 'src/template'
148
- else
149
- default_root = 'public'
150
- end
151
-
152
- setting :root, :default => default_root, :doc => 'The default root directory where template files reside'
153
-
154
- # The default template name.
155
-
156
- setting :default, :default => 'index', :doc => 'The default template name'
157
-
158
- # The default template file extension.
159
-
160
- setting :extension, :default => 'xhtml', :doc => 'The default template file extension'
161
-
162
- # Strip xml comments from templates?
163
-
164
- setting :strip_xml_comments, :default => false, :doc => 'Strip xml comments from templates?'
165
-
166
- class << self
167
- include TemplateMixin
168
- alias_method :compile, :compile_template
169
- alias_method :transform, :compile_template
170
- alias_method :evaluate, :evaluate_template
171
- alias_method :process, :process_template
172
- end
173
-
174
- include TemplateMixin
175
-
176
- # Helper.
177
-
178
- def render(template)
179
- str = ''
180
- process_template(template, 'str', binding)
181
- return str
182
- end
183
- end
184
-
185
- # A Template that reads from files and also
186
- # provides a simple but effective caching scheme.
187
- # An intuitive binding mechanism provides the
188
- # expansion environment.
189
-
190
- class FileTemplate < OpenObject
191
- include TemplateMixin
192
-
193
- @@compiled_template_cache = {}
194
-
195
- attr_accessor :template_filename
196
-
197
- def initialize(filename = nil)
198
- super
199
- @template_filename = filename
200
- end
201
-
202
- def process
203
- __out__ = ''
204
-
205
- unless compiled = @@compiled_template_cache[@template_filename]
206
- template = File.read(@template_filename)
207
- compiled = compile_template(template, '__out__')
208
- @@compiled_template_cache[@template_filename] = compiled
209
- end
210
-
211
- evaluate_template(compiled, binding)
212
-
213
- return __out__
214
- end
215
- end
216
-
217
- end
218
-
219
- # * George Moschovitis <gm@navel.gr>