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,188 +0,0 @@
1
- module Hobo
2
-
3
- module Dryml
4
-
5
- class DrymlSyntaxError < RuntimeError; end
6
-
7
- class DrymlException < Exception
8
- def initialize(message, path=nil, line_num=nil)
9
- if path && line_num
10
- super(message + " -- at #{path}:#{line_num}")
11
- else
12
- super(message)
13
- end
14
- end
15
- end
16
-
17
- TagDef = Struct.new "TagDef", :name, :attrs, :proc
18
-
19
- RESERVED_WORDS = %w{if for while do class else elsif unless case when module in}
20
-
21
- EMPTY_PAGE = "[tag-page]"
22
-
23
- APPLICATION_TAGLIB = { :src => "taglibs/application" }
24
- CORE_TAGLIB = { :src => "core", :plugin => "hobo" }
25
-
26
- DEFAULT_IMPORTS = (if defined?(ApplicationHelper)
27
- [Hobo::HoboHelper, Hobo::Translations, ApplicationHelper]
28
- else
29
- [Hobo::HoboHelper, Hobo::Translations]
30
- end)
31
-
32
- @renderer_classes = {}
33
- @tag_page_renderer_classes = {}
34
-
35
- extend self
36
-
37
- attr_accessor :last_if
38
-
39
- def enable
40
- ActionView::Template.register_template_handler("dryml", Hobo::Dryml::TemplateHandler)
41
- if ActionView::Template.respond_to? :exempt_from_layout
42
- ActionView::Template.exempt_from_layout('dryml')
43
- elsif
44
- ActionView::Base.exempt_from_layout('dryml')
45
- end
46
- DrymlGenerator.enable
47
- end
48
-
49
-
50
- def precompile_taglibs
51
- Dir.chdir(RAILS_ROOT) do
52
- taglibs = Dir["vendor/plugins/**/taglibs/**/*.dryml"] + Dir["app/views/taglibs/**/*.dryml"]
53
- taglibs.each do |f|
54
- Hobo::Dryml::Taglib.get(:template_dir => File.dirname(f), :src => File.basename(f).remove(".dryml"))
55
- end
56
- end
57
- end
58
-
59
-
60
- def clear_cache
61
- @renderer_classes = {}
62
- @tag_page_renderer_classes = {}
63
- end
64
-
65
- def render_tag(view, tag, options={})
66
- renderer = empty_page_renderer(view)
67
- renderer.render_tag(tag, options)
68
- end
69
-
70
-
71
- def empty_page_renderer(view)
72
- controller_name = view.controller.class.name.underscore.sub(/_controller$/, "")
73
- page_renderer(view, [], "#{controller_name}/#{EMPTY_PAGE}")
74
- end
75
-
76
-
77
- def page_renderer_for_template(view, local_names, template)
78
- page_renderer(view, local_names, template.path_without_extension, template.filename)
79
- end
80
-
81
-
82
- def page_renderer(view, local_names=[], page=nil, filename=nil)
83
- if RAILS_ENV == "development"
84
- clear_cache
85
- Taglib.clear_cache
86
- end
87
-
88
- prepare_view!(view)
89
- included_taglibs = ([subsite_taglib(page)] + controller_taglibs(view.controller.class)).compact
90
-
91
- if page.ends_with?(EMPTY_PAGE)
92
- # DELETE ME: controller_class = controller_class_for(page)
93
- controller_class = view.controller.class
94
- @tag_page_renderer_classes[controller_class.name] ||=
95
- make_renderer_class("", page, local_names, DEFAULT_IMPORTS, included_taglibs)
96
- @tag_page_renderer_classes[controller_class.name].new(page, view)
97
- else
98
- filename ||= if view.view_paths.respond_to? :find_template
99
- # Rails 2.3
100
- view.view_paths.find_template(page + ".dryml").filename
101
- else
102
- # Rails 2.2
103
- view._pick_template(page + ".dryml").filename
104
- end
105
- mtime = File.mtime(filename)
106
- renderer_class = @renderer_classes[page]
107
-
108
- # do we need to recompile?
109
- if (!renderer_class || # nothing cached?
110
- (local_names - renderer_class.compiled_local_names).any? || # any new local names?
111
- renderer_class.load_time < mtime) # cache out of date?
112
- renderer_class = make_renderer_class(File.read(filename), filename, local_names,
113
- DEFAULT_IMPORTS, included_taglibs)
114
- renderer_class.load_time = mtime
115
- @renderer_classes[page] = renderer_class
116
- end
117
- renderer_class.new(page, view)
118
- end
119
- end
120
-
121
-
122
- # TODO: Delete this - not needed (use view.controller.class)
123
- def controller_class_for(page)
124
- controller, view = Controller.controller_and_view_for(page)
125
- "#{controller.camelize}Controller".constantize
126
- end
127
-
128
-
129
- def controller_taglibs(controller_class)
130
- controller_class.try.included_taglibs || []
131
- end
132
-
133
-
134
- def subsite_taglib(page)
135
- parts = page.split("/")
136
- subsite = parts.length >= 3 ? parts[0..-3].join('_') : "front"
137
- src = "taglibs/#{subsite}_site"
138
- { :src => src } if File.exists?("#{RAILS_ROOT}/app/views/#{src}.dryml")
139
- end
140
-
141
-
142
- def prepare_view!(view)
143
- # Not sure why this isn't done for me...
144
- # There's probably a button to press round here somewhere
145
- for var in %w(@flash @cookies @action_name @_session @_request @request_origin
146
- @template @request @ignore_missing_templates @_headers @variables_added
147
- @_flash @response @template_class
148
- @_cookies @before_filter_chain_aborted @url
149
- @_response @template_root @headers @_params @params @session)
150
- unless @view.instance_variables.include?(var)
151
- view.instance_variable_set(var, view.controller.instance_variable_get(var))
152
- end
153
- end
154
- end
155
-
156
-
157
- def make_renderer_class(template_src, template_path, locals, imports, included_taglibs=[])
158
- renderer_class = Class.new(TemplateEnvironment)
159
- compile_renderer_class(renderer_class, template_src, template_path, locals, imports, included_taglibs)
160
- renderer_class
161
- end
162
-
163
-
164
- def compile_renderer_class(renderer_class, template_src, template_path, locals, imports, included_taglibs=[])
165
- template = Dryml::Template.new(template_src, renderer_class, template_path)
166
- imports.each {|m| template.import_module(m)}
167
-
168
- taglibs = [CORE_TAGLIB, APPLICATION_TAGLIB] + included_taglibs
169
-
170
- # the sum of all the names we've seen so far - eventually we'll be ready for all of 'em
171
- all_local_names = renderer_class.compiled_local_names | locals
172
-
173
- template.compile(all_local_names, taglibs)
174
- end
175
-
176
-
177
- def unreserve(word)
178
- word = word.to_s
179
- if RESERVED_WORDS.include?(word)
180
- word + "_"
181
- else
182
- word
183
- end
184
- end
185
-
186
- end
187
-
188
- end
@@ -1,140 +0,0 @@
1
- module Hobo::Dryml
2
-
3
- class DRYMLBuilder
4
-
5
- def initialize(template)
6
- @template = template
7
- @build_instructions = nil # set to [] on the first add_build_instruction
8
- @part_names = []
9
- end
10
-
11
- attr_reader :template
12
-
13
- def template_path
14
- template.template_path
15
- end
16
-
17
-
18
- def set_environment(environment)
19
- @environment = environment
20
- end
21
-
22
-
23
- def ready?(mtime, d=false)
24
- @build_instructions && @last_build_mtime && @last_build_mtime >= mtime
25
- end
26
-
27
-
28
- def start
29
- @part_names.clear
30
- @build_instructions = []
31
- end
32
-
33
-
34
- def add_build_instruction(type, params)
35
- @build_instructions << params.merge(:type => type)
36
- end
37
-
38
-
39
- def add_part(name, src, line_num)
40
- raise DrymlException.new("duplicate part: #{name}", template_path, line_num) if name.in?(@part_names)
41
- add_build_instruction(:def, :src => src, :line_num => line_num)
42
- @part_names << name
43
- end
44
-
45
-
46
- def <<(params)
47
- @build_instructions << params
48
- end
49
-
50
-
51
- def render_page_source(src, local_names)
52
- locals = local_names.map{|l| "#{l} = __local_assigns__[:#{l}];"}.join(' ')
53
-
54
- ("def render_page(__page_this__, __local_assigns__); " +
55
- "#{locals} new_object_context(__page_this__) do " +
56
- src +
57
- "; output_buffer; end; end")
58
- end
59
-
60
-
61
- def erb_process(erb_src, method_def=false)
62
- trim_mode = ActionView::TemplateHandlers::ERB.erb_trim_mode
63
- erb = ERB.new(erb_src, nil, trim_mode, "output_buffer")
64
- src = erb.src.split(';')[1..-2].join(';')
65
-
66
- if method_def
67
- src.sub /^\s*def.*?\(.*?\)/, '\0 __in_erb_template=true; '
68
- else
69
- "__in_erb_template=true; " + src
70
- end
71
- end
72
-
73
-
74
- def build(local_names, auto_taglibs, src_mtime)
75
-
76
- auto_taglibs.each { |t| import_taglib(t) }
77
-
78
- @build_instructions._?.each do |instruction|
79
- name = instruction[:name]
80
- case instruction[:type]
81
- when :eval
82
- @environment.class_eval(instruction[:src], template_path, instruction[:line_num])
83
-
84
- when :def
85
- src = erb_process(instruction[:src], true)
86
- @environment.class_eval(src, template_path, instruction[:line_num])
87
-
88
- when :render_page
89
- method_src = render_page_source(erb_process(instruction[:src]), local_names)
90
- @environment.compiled_local_names = local_names
91
- @environment.class_eval(method_src, template_path, instruction[:line_num])
92
-
93
- when :include
94
- import_taglib(instruction)
95
-
96
- when :module
97
- import_module(name.constantize, instruction[:as])
98
-
99
- when :set_theme
100
- set_theme(name)
101
-
102
- when :alias_method
103
- @environment.send(:alias_method, instruction[:new], instruction[:old])
104
-
105
- else
106
- raise RuntimeError.new("DRYML: Unknown build instruction :#{instruction[:type]}, " +
107
- "building #{template_path}")
108
- end
109
- end
110
- @last_build_mtime = src_mtime
111
- end
112
-
113
-
114
- def import_taglib(options)
115
- if options[:module]
116
- import_module(options[:module].constantize, options[:as])
117
- else
118
- template_dir = File.dirname(template_path)
119
- options = options.merge(:template_dir => template_dir)
120
-
121
- taglib = Taglib.get(options)
122
- taglib.import_into(@environment, options[:as])
123
- end
124
- end
125
-
126
-
127
- def import_module(mod, as=nil)
128
- raise NotImplementedError if as
129
- @environment.send(:include, mod)
130
- end
131
-
132
-
133
- def set_theme(name)
134
- if Hobo.current_theme.nil? or Hobo.current_theme == name
135
- Hobo.current_theme = name
136
- import_taglib(:src => "taglibs/themes/#{name}/#{name}")
137
- end
138
- end
139
- end
140
- end
@@ -1,159 +0,0 @@
1
- require 'rexml/xpath'
2
-
3
- module Hobo
4
-
5
- module Dryml
6
-
7
- # DrymlDoc provides the facility to parse a directory tree of DRYML taglibs, building a collection of objects that provide metadata
8
- module DrymlDoc
9
-
10
- def self.load_taglibs(directory, taglib_class=DrymlDoc::Taglib)
11
- dryml_files = Dir["#{directory}/**/*.dryml"]
12
-
13
- dryml_files.map { |f| taglib_class.new(directory, f) }
14
- end
15
-
16
- CommentMethods = classy_module do
17
-
18
- def comment_intro
19
- comment && comment =~ /(.*?)^#/m ? $1 : comment
20
- end
21
-
22
-
23
- def comment_rest
24
- comment && comment[comment_intro.length..-1]
25
- end
26
-
27
- %w(comment comment_intro comment_rest).each do |m|
28
- class_eval "def #{m}_html; Maruku.new(#{m}).to_html.gsub(/&amp;/, '&'); end"
29
- end
30
-
31
- end
32
-
33
- class Taglib
34
-
35
- def initialize(home, filename, name=nil)
36
- @name = name || filename.sub(/.dryml$/, '')[home.length+1..-1]
37
- @doc = Hobo::Dryml::Parser::Document.new(File.read(filename), filename)
38
- parse_tag_defs
39
- end
40
-
41
- attr_reader :name, :doc, :tag_defs
42
-
43
- def comment
44
- first_node = doc[0][0]
45
- doc.restore_erb_scriptlets(first_node.to_s.strip) if first_node.is_a?(REXML::Comment)
46
- end
47
-
48
- include CommentMethods
49
-
50
- private
51
-
52
- def tagdef_class
53
- self.class.parent.const_get('TagDef')
54
- end
55
-
56
- def parse_tag_defs
57
- @tag_defs = []
58
- REXML::XPath.match(doc, '/*/*[@tag]').each { |node| @tag_defs << tagdef_class.new(self, node) }
59
- end
60
-
61
- end
62
-
63
- class TagDef
64
-
65
- def initialize(taglib, node)
66
- @taglib = taglib
67
- @node = node
68
- end
69
-
70
- attr_reader :taglib, :node
71
- delegate :doc, :to => :taglib
72
-
73
-
74
- def name
75
- node.attributes['tag']
76
- end
77
-
78
- def source
79
- doc.restore_erb_scriptlets(node.to_s).strip
80
- end
81
-
82
- # The contents of the XML comment, if any, immediately above the tag definition
83
- def comment
84
- @comment ||= begin
85
- space = node.previous_sibling and
86
- space.to_s.blank? && space.to_s.count("\n") == 1 and
87
- comment_node = space.previous_sibling
88
-
89
- if comment_node.is_a?(REXML::Comment)
90
- doc.restore_erb_scriptlets(comment_node.to_s.strip)
91
- end
92
- end
93
- end
94
-
95
- include CommentMethods
96
-
97
- def no_doc?
98
- comment =~ /^nodoc\b/
99
- end
100
-
101
- # An array of the arrtibute names defined by this tag
102
- def attributes
103
- (node.attributes['attrs'] || "").split(/\s*,\s*/).where_not.blank?
104
- end
105
-
106
-
107
- # Returns a recursive array srtucture, where each item in the array is a pair: [parameter_name, sub_parameters]
108
- # (sub-parameters is the same kind of structure)
109
- def parameters(element=node)
110
- result = []
111
- element.elements.each do |e|
112
- if (p = e.attributes['param'])
113
- param_name = p == "&true" ? e.name : p
114
- result << [param_name, parameters(e)]
115
- else
116
- result.concat(parameters(e))
117
- end
118
- end
119
- result
120
- end
121
-
122
-
123
- # Is this the base definition of a polymorphic tag
124
- def polymorphic?
125
- node.attributes['polymorphic'].present?
126
- end
127
-
128
- # Is this an <extend>?
129
- def extension?
130
- node.name == "extend"
131
- end
132
-
133
-
134
- # The definition's 'for' attribute
135
- def for_type
136
- node.attributes['for']
137
- end
138
-
139
-
140
- # The name of the tag, if any, that this definition merges its parameters into
141
- # That is, the tag with 'merge' or 'merge-params' declared
142
- def merge_params
143
- REXML::XPath.first(node, ".//*[@merge|@merge-params]")._?.name
144
- end
145
-
146
- # The name of the tag, if any, that this definition merges its attributes into
147
- # That is, the tag with 'merge' or 'merge-attrs' declared
148
- def merge_attrs
149
- REXML::XPath.first(node, ".//*[@merge|@merge-attrs]")._?.name
150
- end
151
-
152
- end
153
-
154
-
155
- end
156
-
157
- end
158
-
159
- end