hobo 1.0.3 → 1.1.0.pre0

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