hobo 1.0.3 → 1.1.0.pre0

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 (64) hide show
  1. data/CHANGES.txt +0 -66
  2. data/README +3 -0
  3. data/Rakefile +7 -7
  4. data/doctest/model.rdoctest +0 -2
  5. data/doctest/multi_model_forms.rdoctest +0 -2
  6. data/doctest/scopes.rdoctest +13 -21
  7. data/lib/active_record/association_collection.rb +7 -16
  8. data/lib/hobo.rb +10 -65
  9. data/lib/hobo/accessible_associations.rb +1 -5
  10. data/lib/hobo/authentication_support.rb +1 -1
  11. data/lib/hobo/controller.rb +5 -5
  12. data/lib/hobo/hobo_helper.rb +0 -84
  13. data/lib/hobo/lifecycles/lifecycle.rb +37 -31
  14. data/lib/hobo/lifecycles/transition.rb +1 -2
  15. data/lib/hobo/model.rb +13 -21
  16. data/lib/hobo/model_controller.rb +8 -8
  17. data/lib/hobo/rapid_helper.rb +12 -1
  18. data/lib/hobo/scopes/automatic_scopes.rb +26 -13
  19. data/lib/hobo/scopes/named_scope_extensions.rb +16 -28
  20. data/lib/hobo/user_controller.rb +1 -0
  21. data/lib/hobo/view_hints.rb +1 -5
  22. data/rails_generators/hobo/templates/initializer.rb +1 -1
  23. data/rails_generators/hobo_front_controller/templates/summary.dryml +4 -2
  24. data/rails_generators/hobo_model/hobo_model_generator.rb +12 -0
  25. data/rails_generators/hobo_model/templates/model.rb +9 -2
  26. data/rails_generators/hobo_rapid/templates/hobo-rapid.js +98 -23
  27. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +1 -1
  28. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +3 -1
  29. data/{dryml_generators → rapid_generators}/rapid/cards.dryml.erb +0 -0
  30. data/{dryml_generators → rapid_generators}/rapid/forms.dryml.erb +0 -0
  31. data/{dryml_generators → rapid_generators}/rapid/pages.dryml.erb +1 -1
  32. data/taglibs/rapid.dryml +2 -0
  33. data/taglibs/rapid_core.dryml +10 -9
  34. data/taglibs/rapid_forms.dryml +70 -35
  35. data/taglibs/rapid_lifecycles.dryml +17 -4
  36. data/taglibs/rapid_plus.dryml +3 -3
  37. data/taglibs/rapid_summary.dryml +11 -0
  38. data/taglibs/rapid_user_pages.dryml +39 -28
  39. data/tasks/hobo_tasks.rake +1 -1
  40. metadata +45 -61
  41. data/hobo.gemspec +0 -226
  42. data/lib/hobo/dryml.rb +0 -188
  43. data/lib/hobo/dryml/dryml_builder.rb +0 -140
  44. data/lib/hobo/dryml/dryml_doc.rb +0 -159
  45. data/lib/hobo/dryml/dryml_generator.rb +0 -263
  46. data/lib/hobo/dryml/dryml_support_controller.rb +0 -13
  47. data/lib/hobo/dryml/parser.rb +0 -3
  48. data/lib/hobo/dryml/parser/attribute.rb +0 -41
  49. data/lib/hobo/dryml/parser/base_parser.rb +0 -254
  50. data/lib/hobo/dryml/parser/document.rb +0 -57
  51. data/lib/hobo/dryml/parser/element.rb +0 -27
  52. data/lib/hobo/dryml/parser/elements.rb +0 -45
  53. data/lib/hobo/dryml/parser/source.rb +0 -58
  54. data/lib/hobo/dryml/parser/text.rb +0 -13
  55. data/lib/hobo/dryml/parser/tree_parser.rb +0 -67
  56. data/lib/hobo/dryml/part_context.rb +0 -137
  57. data/lib/hobo/dryml/scoped_variables.rb +0 -42
  58. data/lib/hobo/dryml/tag_parameters.rb +0 -36
  59. data/lib/hobo/dryml/taglib.rb +0 -123
  60. data/lib/hobo/dryml/template.rb +0 -1019
  61. data/lib/hobo/dryml/template_environment.rb +0 -613
  62. data/lib/hobo/dryml/template_handler.rb +0 -187
  63. data/lib/hobo/static_tags +0 -98
  64. data/taglibs/core.dryml +0 -104
@@ -1,57 +0,0 @@
1
- module Hobo::Dryml
2
-
3
- module Parser
4
-
5
- class Document < REXML::Document
6
-
7
- def initialize(source, path)
8
- super(nil)
9
-
10
- # Replace <%...%> scriptlets with xml-safe references into a hash of scriptlets
11
- @scriptlets = {}
12
- source = source.gsub(/<%(.*?)%>/m) do
13
- _, scriptlet = *Regexp.last_match
14
- id = @scriptlets.size + 1
15
- @scriptlets[id] = scriptlet
16
- newlines = "\n" * scriptlet.count("\n")
17
- "[![DRYML-ERB#{id}#{newlines}]!]"
18
- end
19
-
20
-
21
- @reference_src = "<dryml_page>" + source + "</dryml_page>"
22
- rex_src = Hobo::Dryml::Parser::Source.new(@reference_src)
23
-
24
- @elements = Hobo::Dryml::Parser::Elements.new(self)
25
- build(rex_src)
26
-
27
- rescue REXML::ParseException => e
28
- raise Hobo::Dryml::DrymlSyntaxError, "File: #{path}\n#{e}"
29
- end
30
-
31
-
32
- def element_line_num(el)
33
- offset = el.source_offset
34
- @reference_src[0..offset].count("\n") + 1
35
- end
36
-
37
-
38
- def default_attribute_value
39
- "&true"
40
- end
41
-
42
-
43
- def restore_erb_scriptlets(src)
44
- src.gsub(/\[!\[DRYML-ERB(\d+)\s*\]!\]/m) {|s| "<%#{@scriptlets[$1.to_i]}%>" }
45
- end
46
-
47
-
48
- private
49
- def build( source )
50
- Hobo::Dryml::Parser::TreeParser.new( source, self ).parse
51
- end
52
-
53
- end
54
-
55
- end
56
-
57
- end
@@ -1,27 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class Element < REXML::Element
4
-
5
- def initialize(*args)
6
- super
7
- @elements = Hobo::Dryml::Parser::Elements.new(self)
8
- end
9
-
10
- def dryml_name
11
- expanded_name.sub(/:.*/, "")
12
- end
13
-
14
- attr_accessor :start_tag_source, :source_offset
15
-
16
- attr_writer :has_end_tag
17
- def has_end_tag?
18
- @has_end_tag
19
- end
20
-
21
- def parameter_tag?
22
- expanded_name =~ /:$/
23
- end
24
-
25
- end
26
-
27
- end
@@ -1,45 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class Element < REXML::Element
4
-
5
- def initialize(*args)
6
- super
7
- @elements = Hobo::Dryml::Parser::Elements.new(self)
8
- end
9
-
10
- def dryml_name
11
- expanded_name.sub(/:.*/, "")
12
- end
13
-
14
- attr_accessor :start_tag_source, :source_offset
15
-
16
- attr_writer :has_end_tag
17
- def has_end_tag?
18
- @has_end_tag
19
- end
20
-
21
- def parameter_tag?
22
- expanded_name =~ /:$/
23
- end
24
-
25
- end
26
-
27
- class Elements < REXML::Elements
28
-
29
- # Override to ensure DRYML elements are created
30
- def add(element=nil)
31
- rv = nil
32
- if element.nil?
33
- Hobo::Dryml::Parser::Element.new("", self, @element.context)
34
- elsif not element.kind_of?(Element)
35
- Hobo::Dryml::Parser::Element.new(element, self, @element.context)
36
- else
37
- @element << element
38
- element.context = @element.context
39
- element
40
- end
41
- end
42
-
43
- end
44
-
45
- end
@@ -1,58 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- # A REXML source that keeps track of where in the buffer it is
4
- class Source < REXML::Source
5
-
6
- def initialize(src)
7
- super(src)
8
- @buffer_offset = 0
9
- end
10
-
11
- attr_reader :last_match_offset
12
-
13
- def remember_match(m)
14
- if m
15
- @last_match = m
16
- @last_match_offset = @buffer_offset + m.begin(0)
17
- @orig[@last_match_offset..@last_match_offset+m[0].length] == @buffer[m.begin(0)..m.end(0)]
18
- end
19
- m
20
- end
21
-
22
- def advance_buffer(md)
23
- @buffer = md.post_match
24
- @buffer_offset += md.end(0)
25
- end
26
-
27
- def scan(pattern, cons=false)
28
- raise '!'
29
- return nil if @buffer.nil?
30
- rv = @buffer.scan(pattern)
31
- if cons and rv.size > 0
32
- advance_buffer(Regexp.last_match)
33
- end
34
- rv
35
- end
36
-
37
- def consume(pattern)
38
- md = remember_match(pattern.match(@buffer))
39
- if md
40
- advance_buffer(md)
41
- @buffer
42
- end
43
- end
44
-
45
- def match(pattern, cons=false)
46
- md = remember_match(pattern.match(@buffer))
47
- advance_buffer(md) if cons and md
48
- return md
49
- end
50
-
51
- def current_line
52
- pos = last_match_offset || 0
53
- [0, 0, @orig[0..pos].count("\n") + 1]
54
- end
55
-
56
- end
57
-
58
- end
@@ -1,13 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class Text < REXML::Text
4
-
5
- def parent=(parent)
6
- # Bypass immediate super
7
- REXML::Child.instance_method(:parent=).bind(self).call(parent)
8
- Text.check(@string, /</, nil) if @raw and @parent && Text.respond_to?(:check)
9
- end
10
-
11
- end
12
-
13
- end
@@ -1,67 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class TreeParser < REXML::Parsers::TreeParser
4
- def initialize( source, build_context = Document.new )
5
- @build_context = build_context
6
- @parser = Hobo::Dryml::Parser::BaseParser.new(source)
7
- end
8
-
9
-
10
- def parse
11
- tag_stack = []
12
- in_doctype = false
13
- entities = nil
14
- begin
15
- while true
16
- event = @parser.pull
17
- #STDERR.puts "TREEPARSER GOT #{event.inspect}"
18
- case event[0]
19
- when :end_document
20
- unless tag_stack.empty?
21
- #raise ParseException.new("No close tag for #{tag_stack.inspect}")
22
- raise ParseException.new("No close tag for #{@build_context.xpath}")
23
- end
24
- return
25
- when :start_element
26
- tag_stack.push(event[1])
27
- el = @build_context = @build_context.add_element( event[1] )
28
- event[2].each do |key, value|
29
- el.attributes[key]=Hobo::Dryml::Parser::Attribute.new(key,value,self)
30
- end
31
- @build_context.start_tag_source = event[3]
32
- @build_context.source_offset = event[4]
33
- when :end_element
34
- tag_stack.pop
35
- @build_context.has_end_tag = event[2]
36
- @build_context = @build_context.parent
37
- when :text
38
- if not in_doctype
39
- if @build_context[-1].instance_of? Text
40
- @build_context[-1] << event[1]
41
- else
42
- @build_context.add(
43
- Hobo::Dryml::Parser::Text.new(event[1], @build_context.whitespace, nil, true)
44
- ) unless (
45
- @build_context.ignore_whitespace_nodes and
46
- event[1].strip.size==0
47
- )
48
- end
49
- end
50
- when :comment
51
- c = REXML::Comment.new( event[1] )
52
- @build_context.add( c )
53
- when :cdata
54
- c = REXML::CData.new( event[1] )
55
- @build_context.add( c )
56
- when :processing_instruction
57
- @build_context.add( Instruction.new( event[1], event[2] ) )
58
- end
59
- end
60
- rescue REXML::Validation::ValidationException
61
- raise
62
- rescue
63
- raise REXML::ParseException.new( $!.message, @parser.source, @parser, $! )
64
- end
65
- end
66
- end
67
- end
@@ -1,137 +0,0 @@
1
- module Hobo
2
-
3
- module Dryml
4
-
5
- # Raised when the part context fails its integrity check.
6
- class PartContext
7
-
8
- class TamperedWithPartContext < StandardError; end
9
-
10
- class TypedId < String; end
11
-
12
- class << self
13
- attr_accessor :secret, :digest
14
- end
15
- self.digest = 'SHA1'
16
-
17
-
18
- def self.client_side_storage(contexts, session)
19
- return "" if contexts.empty?
20
-
21
- contexts.map do |dom_id, context|
22
- code = context.marshal(session).split("\n").map{|line| "'#{line}\\n'"}.join(" +\n ")
23
- "hoboParts['#{dom_id}'] = (#{code});\n"
24
- end.join
25
- end
26
-
27
-
28
- def self.pre_marshal(x)
29
- if x.is_a?(ActiveRecord::Base) && x.respond_to?(:typed_id)
30
- TypedId.new(x.typed_id)
31
- else
32
- x
33
- end
34
- end
35
-
36
-
37
- def self.for_call(part_name, environment, locals)
38
- new do |c|
39
- c.part_name = part_name
40
- c.locals = locals.map { |l| pre_marshal(l) }
41
- c.this_id = environment.typed_id
42
- c.form_field_path = environment.form_field_path
43
- end
44
- end
45
-
46
-
47
- def self.for_refresh(encoded_context, page_this, session)
48
- new do |c|
49
- c.unmarshal(encoded_context, page_this, session)
50
- end
51
- end
52
-
53
-
54
- def initialize
55
- yield self
56
- end
57
-
58
- attr_accessor :part_name, :locals, :this, :this_field, :this_id, :form_field_path
59
-
60
-
61
- def marshal(session)
62
- context = [@part_name, @this_id, @locals]
63
- context << form_field_path if form_field_path
64
- data = Base64.encode64(Marshal.dump(context)).strip
65
- digest = generate_digest(data, session)
66
- "#{data}--#{digest}"
67
- end
68
-
69
-
70
- # Unmarshal part context to a hash and verify its integrity.
71
- def unmarshal(client_store, page_this, session)
72
- data, digest = CGI.unescape(client_store).strip.split('--')
73
-
74
- raise TamperedWithPartContext unless digest == generate_digest(data, session)
75
-
76
- context = Marshal.load(Base64.decode64(data))
77
-
78
- part_name, this_id, locals, form_field_path = context
79
-
80
- if RAILS_DEFAULT_LOGGER
81
- RAILS_DEFAULT_LOGGER.info "Call part: #{part_name}. this-id = #{this_id}, locals = #{locals.inspect}"
82
- RAILS_DEFAULT_LOGGER.info " : form_field_path = #{form_field_path.inspect}" if form_field_path
83
- end
84
-
85
- self.part_name = part_name
86
- self.this_id = this_id
87
- self.locals = restore_locals(locals)
88
- self.form_field_path = form_field_path
89
-
90
- parse_this_id(page_this)
91
- end
92
-
93
-
94
- # Generate the HMAC keyed message digest. Uses SHA1 by default.
95
- def generate_digest(data, session)
96
- secret = self.class.secret || ActionController::Base.session_options[:secret] || ActionController::Base.cached_session_options.first[:secret]
97
- key = secret.respond_to?(:call) ? secret.call(session) : secret
98
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(self.class.digest), key, data)
99
- end
100
-
101
-
102
-
103
- def parse_this_id(page_this)
104
- if this_id == "this"
105
- self.this = page_this
106
- elsif this_id =~ /^this:(.*)/
107
- self.this = page_this
108
- self.this_field = $1
109
- elsif this_id == "nil"
110
- nil
111
- else
112
- parts = this_id.split(':')
113
- if parts.length == 3
114
- self.this = Hobo::Model.find_by_typed_id("#{parts[0]}:#{parts[1]}")
115
- self.this_field = parts[2]
116
- else
117
- self.this = Hobo::Model.find_by_typed_id(this_id)
118
- end
119
- end
120
- end
121
-
122
-
123
- def restore_locals(locals)
124
- locals.map do |l|
125
- if l.is_a?(TypedId)
126
- Hobo::Model.find_by_typed_id(l)
127
- else
128
- l
129
- end
130
- end
131
- end
132
-
133
- end
134
-
135
- end
136
-
137
- end
@@ -1,42 +0,0 @@
1
- module Hobo::Dryml
2
-
3
- class ScopedVariables
4
-
5
- def initialize(variables=nil)
6
- @scopes = variables ? [variables] : []
7
- end
8
-
9
- def [](key)
10
- s = scope_with_key(key) and s[key]
11
- end
12
-
13
- def []=(key, val)
14
- s = scope_with_key(key) or raise ArgumentError, "no such scoped variable: #{key}"
15
- s[key] = val
16
- end
17
-
18
- def new_scope(variables)
19
- @scopes << variables.dup
20
- res = yield
21
- @scopes.pop
22
- res
23
- end
24
-
25
- def scope_with_key(key)
26
- @scopes.reverse_each do |s|
27
- return s if s.has_key?(key)
28
- end
29
- nil
30
- end
31
-
32
- def method_missing(name, *args)
33
- if name.to_s =~ /=$/
34
- self[name.to_s[0..-2].to_sym] = args.first
35
- else
36
- self[name]
37
- end
38
- end
39
-
40
- end
41
-
42
- end