glue 0.31.0 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
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>