hobo 0.7.4 → 0.7.5
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.
- data/bin/hobo +0 -6
- data/hobo_files/plugin/CHANGES.txt +103 -0
- data/hobo_files/plugin/Rakefile +2 -0
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +1 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/IE7.js +2 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +28 -12
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/{application.css → clean.css} +10 -9
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +1 -1
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/views/{application.dryml → clean.dryml} +0 -0
- data/hobo_files/plugin/init.rb +7 -3
- data/hobo_files/plugin/lib/hobo.rb +3 -1
- data/hobo_files/plugin/lib/hobo/bundle.rb +24 -14
- data/hobo_files/plugin/lib/hobo/dryml.rb +5 -1
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +1 -1
- data/hobo_files/plugin/lib/hobo/dryml/parser/base_parser.rb +11 -10
- data/hobo_files/plugin/lib/hobo/dryml/parser/document.rb +37 -10
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +5 -22
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +1 -1
- data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +10 -2
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +7 -0
- data/hobo_files/plugin/lib/hobo/model.rb +18 -13
- data/hobo_files/plugin/lib/hobo/model_controller.rb +45 -54
- data/hobo_files/plugin/lib/hobo/model_router.rb +8 -1
- data/hobo_files/plugin/lib/hobo/scopes.rb +3 -4
- data/hobo_files/plugin/lib/hobo/scopes/automatic_scopes.rb +3 -0
- data/hobo_files/plugin/taglib-docs/core.markdown +165 -0
- data/hobo_files/plugin/taglib-docs/rapid.markdown +677 -0
- data/hobo_files/plugin/taglib-docs/rapid_document_tags.markdown +240 -0
- data/hobo_files/plugin/taglib-docs/rapid_editing.markdown +418 -0
- data/hobo_files/plugin/taglib-docs/rapid_forms.markdown +562 -0
- data/hobo_files/plugin/taglib-docs/rapid_generics.markdown +187 -0
- data/hobo_files/plugin/taglib-docs/rapid_navigation.markdown +214 -0
- data/hobo_files/plugin/taglib-docs/rapid_pages.markdown +530 -0
- data/hobo_files/plugin/taglib-docs/rapid_plus.markdown +65 -0
- data/hobo_files/plugin/taglib-docs/rapid_support.markdown +50 -0
- data/hobo_files/plugin/taglib-docs/rapid_user_pages.markdown +129 -0
- data/hobo_files/plugin/taglibs/rapid.dryml +2 -2
- data/hobo_files/plugin/taglibs/rapid_forms.dryml +7 -22
- data/hobo_files/plugin/taglibs/rapid_generics.dryml +14 -12
- data/hobo_files/plugin/taglibs/rapid_navigation.dryml +5 -4
- data/hobo_files/plugin/taglibs/rapid_pages.dryml +5 -1
- data/hobo_files/plugin/tasks/fix_dryml.rake +1 -1
- data/hobo_files/plugin/tasks/generate_tag_reference.rb +162 -0
- data/hobo_files/plugin/tasks/hobo_tasks.rake +17 -0
- metadata +46 -5
@@ -2,20 +2,47 @@ module Hobo::Dryml::Parser
|
|
2
2
|
|
3
3
|
class Document < REXML::Document
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize(source, path)
|
6
|
+
super(nil)
|
7
|
+
|
8
|
+
# Replace <%...%> scriptlets with xml-safe references into a hash of scriptlets
|
9
|
+
@scriptlets = {}
|
10
|
+
source = source.gsub(/<%(.*?)%>/m) do
|
11
|
+
_, scriptlet = *Regexp.last_match
|
12
|
+
id = @scriptlets.size + 1
|
13
|
+
@scriptlets[id] = scriptlet
|
14
|
+
newlines = "\n" * scriptlet.count("\n")
|
15
|
+
"[![DRYML-ERB#{id}#{newlines}]!]"
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
@reference_src = "<dryml_page>" + source + "</dryml_page>"
|
20
|
+
rex_src = Hobo::Dryml::Parser::Source.new(@reference_src)
|
21
|
+
|
9
22
|
@elements = Hobo::Dryml::Parser::Elements.new(self)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
23
|
+
build(rex_src)
|
24
|
+
|
25
|
+
rescue REXML::ParseException => e
|
26
|
+
raise DrymlSyntaxError, "File: #{path}\n#{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def element_line_num(el)
|
31
|
+
offset = el.source_offset
|
32
|
+
@reference_src[0..offset].count("\n") + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def default_attribute_value
|
37
|
+
"&true"
|
16
38
|
end
|
17
39
|
|
40
|
+
|
41
|
+
def restore_erb_scriptlets(src)
|
42
|
+
src.gsub(/\[!\[DRYML-ERB(\d+)\s*\]!\]/m) {|s| "<%#{@scriptlets[$1.to_i]}%>" }
|
43
|
+
end
|
18
44
|
|
45
|
+
|
19
46
|
private
|
20
47
|
def build( source )
|
21
48
|
Hobo::Dryml::Parser::TreeParser.new( source, self ).parse
|
@@ -89,30 +89,14 @@ module Hobo::Dryml
|
|
89
89
|
|
90
90
|
|
91
91
|
def process_src
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
_, scriptlet = *Regexp.last_match
|
96
|
-
id = @scriptlets.size + 1
|
97
|
-
@scriptlets[id] = scriptlet
|
98
|
-
newlines = "\n" * scriptlet.count("\n")
|
99
|
-
"[![HOBO-ERB#{id}#{newlines}]!]"
|
100
|
-
end
|
101
|
-
|
102
|
-
@xmlsrc = "<dryml_page>" + src + "</dryml_page>"
|
103
|
-
begin
|
104
|
-
@doc = Hobo::Dryml::Parser::Document.new(Hobo::Dryml::Parser::Source.new(@xmlsrc))
|
105
|
-
rescue REXML::ParseException => e
|
106
|
-
raise DrymlSyntaxError, "File: #{@template_path}\n#{e}"
|
107
|
-
end
|
108
|
-
@doc.default_attribute_value = "&true"
|
109
|
-
|
110
|
-
restore_erb_scriptlets(children_to_erb(@doc.root))
|
92
|
+
@doc = Hobo::Dryml::Parser::Document.new(@src, @template_path)
|
93
|
+
result = children_to_erb(@doc.root)
|
94
|
+
restore_erb_scriptlets(result)
|
111
95
|
end
|
112
96
|
|
113
97
|
|
114
98
|
def restore_erb_scriptlets(src)
|
115
|
-
|
99
|
+
@doc.restore_erb_scriptlets(src)
|
116
100
|
end
|
117
101
|
|
118
102
|
|
@@ -896,8 +880,7 @@ module Hobo::Dryml
|
|
896
880
|
end
|
897
881
|
|
898
882
|
def element_line_num(el)
|
899
|
-
|
900
|
-
@xmlsrc[0..offset].count("\n") + 1
|
883
|
+
@doc.element_line_num(el)
|
901
884
|
end
|
902
885
|
|
903
886
|
def tag_newlines(el)
|
@@ -455,7 +455,7 @@ module Hobo::Dryml
|
|
455
455
|
res = (send(method_name, attributes) + part_contexts_javascripts).strip
|
456
456
|
|
457
457
|
# TODO: Temporary hack to get the dryml metadata comments in the right place
|
458
|
-
if RAILS_ENV == "development"
|
458
|
+
if false && RAILS_ENV == "development"
|
459
459
|
res.gsub(/^(.*?)(<!DOCTYPE.*?>).*?(<html.*?>)/m, "\\2\\3\\1")
|
460
460
|
else
|
461
461
|
res
|
@@ -39,16 +39,24 @@ module ActionController
|
|
39
39
|
@dryml_fallback_tag = tag_name
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
|
43
|
+
def call_dryml_tag(tag, options={})
|
43
44
|
add_variables_to_assigns
|
44
45
|
|
46
|
+
# TODO: Figure out what this bit is all about :-)
|
45
47
|
if options[:with]
|
46
48
|
@this = options[:with] unless options[:field]
|
47
49
|
else
|
48
50
|
options[:with] = dryml_context
|
49
51
|
end
|
50
52
|
|
51
|
-
|
53
|
+
Hobo::Dryml.render_tag(@template, tag, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# TODO: This is namespace polution, should be called render_dryml_tag
|
58
|
+
def render_tag(tag, options={}, render_options={})
|
59
|
+
text = call_dryml_tag(tag, options)
|
52
60
|
text && render({:text => text, :layout => false }.merge(render_options))
|
53
61
|
end
|
54
62
|
|
@@ -78,8 +78,6 @@ module Hobo
|
|
78
78
|
send("find_by_#{name_attribute}", *args)
|
79
79
|
end
|
80
80
|
|
81
|
-
alias_method :[], :named
|
82
|
-
|
83
81
|
|
84
82
|
def field_added(name, type, args, options)
|
85
83
|
self.name_attribute = name.to_sym if options.delete(:name)
|
@@ -291,17 +289,20 @@ module Hobo
|
|
291
289
|
|
292
290
|
|
293
291
|
def manage_join_records(association)
|
294
|
-
through = reflections[association].through_reflection
|
295
|
-
source = reflections[association].source_reflection
|
296
292
|
|
297
293
|
method = "manage_join_records_for_#{association}"
|
298
294
|
after_save method
|
299
295
|
class_eval %{
|
300
296
|
def #{method}
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
297
|
+
assigned = #{association}.dup
|
298
|
+
current = #{association}.reload
|
299
|
+
|
300
|
+
through = #{association}.proxy_reflection.through_reflection
|
301
|
+
source = #{association}.proxy_reflection.source_reflection
|
302
|
+
|
303
|
+
to_delete = current - assigned
|
304
|
+
to_add = assigned - current
|
305
|
+
through.klass.delete_all(["\#{through.primary_key_name} = ? and \#{source.primary_key_name} in (?)",
|
305
306
|
self.id, to_delete.*.id]) if to_delete.any?
|
306
307
|
to_add.each { |record| #{association} << record }
|
307
308
|
end
|
@@ -363,7 +364,7 @@ module Hobo
|
|
363
364
|
|
364
365
|
|
365
366
|
def user_view(user, field=nil)
|
366
|
-
raise PermissionDeniedError unless Hobo.can_view?(user, self, field)
|
367
|
+
raise PermissionDeniedError, self.inspect unless Hobo.can_view?(user, self, field)
|
367
368
|
end
|
368
369
|
|
369
370
|
|
@@ -511,9 +512,13 @@ module Hobo
|
|
511
512
|
|
512
513
|
def convert_associated_records_for_mass_assignment(reflection, value)
|
513
514
|
if reflection.macro.in?([:belongs_to, :has_one])
|
514
|
-
if value.is_a?(String)
|
515
|
-
|
516
|
-
|
515
|
+
if value.is_a?(String)
|
516
|
+
if value.starts_with?('@')
|
517
|
+
# TODO: This @foo_1 feature is rarely (never?) used - get rid of it
|
518
|
+
Hobo.object_from_dom_id(value[1..-1])
|
519
|
+
else
|
520
|
+
reflection.klass.named(value)
|
521
|
+
end
|
517
522
|
else
|
518
523
|
value
|
519
524
|
end
|
@@ -521,7 +526,7 @@ module Hobo
|
|
521
526
|
if reflection.klass.try.name_attribute
|
522
527
|
value.map do |x|
|
523
528
|
if x.is_a?(String)
|
524
|
-
reflection.klass
|
529
|
+
reflection.klass.named(x) unless x.blank?
|
525
530
|
else
|
526
531
|
x
|
527
532
|
end
|
@@ -6,7 +6,7 @@ module Hobo
|
|
6
6
|
|
7
7
|
VIEWLIB_DIR = "taglibs"
|
8
8
|
|
9
|
-
|
9
|
+
DONT_PAGINATE_FORMATS = [ Mime::CSV, Mime::YAML, Mime::JSON, Mime::XML, Mime::ATOM, Mime::RSS ]
|
10
10
|
|
11
11
|
READ_ONLY_ACTIONS = [:index, :show]
|
12
12
|
WRITE_ONLY_ACTIONS = [:create, :update, :destroy]
|
@@ -17,9 +17,12 @@ module Hobo
|
|
17
17
|
def included(base)
|
18
18
|
base.class_eval do
|
19
19
|
@auto_actions ||= {}
|
20
|
+
|
21
|
+
inheriting_cattr_reader :web_methods => [], :show_actions => [], :index_actions => []
|
20
22
|
|
21
23
|
extend ClassMethods
|
22
24
|
|
25
|
+
|
23
26
|
helper_method :model, :current_user
|
24
27
|
before_filter :set_no_cache_headers
|
25
28
|
|
@@ -30,7 +33,6 @@ module Hobo
|
|
30
33
|
alias_method_chain :render, :hobo_model
|
31
34
|
|
32
35
|
end
|
33
|
-
base.template_path_cache = {}
|
34
36
|
|
35
37
|
Hobo::Controller.included_in_class(base)
|
36
38
|
end
|
@@ -42,25 +44,12 @@ module Hobo
|
|
42
44
|
|
43
45
|
attr_writer :model
|
44
46
|
|
45
|
-
attr_accessor :template_path_cache
|
46
|
-
|
47
|
-
def web_methods
|
48
|
-
@web_methods ||= superclass.respond_to?(:web_methods) ? superclass.web_methods : []
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
def show_actions
|
53
|
-
@show_actions ||= superclass.respond_to?(:show_actions) ? superclass.show_actions : []
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def index_actions
|
58
|
-
@index_actions ||= superclass.respond_to?(:index_actions) ? superclass.index_actions : []
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
47
|
def collections
|
63
|
-
#
|
48
|
+
# FIXME The behaviour here is weird if the superclass does
|
49
|
+
# define collections *and* this class adds some more. The
|
50
|
+
# added ones won't be published
|
51
|
+
|
52
|
+
# by default By default, all has_many associations are published
|
64
53
|
@collections ||= if superclass.respond_to?(:collections)
|
65
54
|
superclass.collections
|
66
55
|
else
|
@@ -74,10 +63,15 @@ module Hobo
|
|
74
63
|
end
|
75
64
|
|
76
65
|
|
77
|
-
def
|
78
|
-
options = options.
|
79
|
-
|
80
|
-
|
66
|
+
def autocomplete(name, options={}, &block)
|
67
|
+
options = options.dup
|
68
|
+
field = options.delete(:field) || name
|
69
|
+
if block
|
70
|
+
index_action "complete_#{name}", &block
|
71
|
+
else
|
72
|
+
index_action "complete_#{name}" do
|
73
|
+
hobo_completetions name, model, options
|
74
|
+
end
|
81
75
|
end
|
82
76
|
end
|
83
77
|
|
@@ -121,7 +115,7 @@ module Hobo
|
|
121
115
|
end
|
122
116
|
end
|
123
117
|
|
124
|
-
@auto_actions -= except_actions
|
118
|
+
@auto_actions -= except_actions.flatten
|
125
119
|
|
126
120
|
def_auto_actions
|
127
121
|
end
|
@@ -255,10 +249,8 @@ module Hobo
|
|
255
249
|
# --- Action implementation helpers --- #
|
256
250
|
|
257
251
|
|
258
|
-
def find_instance(
|
259
|
-
|
260
|
-
id = args.first || params[:id]
|
261
|
-
model.user_find(current_user, id, options)
|
252
|
+
def find_instance(options={})
|
253
|
+
model.user_find(current_user, params[:id], options)
|
262
254
|
end
|
263
255
|
|
264
256
|
|
@@ -279,17 +271,20 @@ module Hobo
|
|
279
271
|
end
|
280
272
|
|
281
273
|
|
282
|
-
def destination_after_submit(record=nil)
|
274
|
+
def destination_after_submit(record=nil, destroyed=false)
|
283
275
|
record ||= this
|
284
276
|
|
277
|
+
after_submit = params[:after_submit]
|
278
|
+
|
285
279
|
# The after_submit post parameter takes priority
|
286
|
-
|
280
|
+
(after_submit == "stay-here" ? :back : after_submit) ||
|
281
|
+
|
287
282
|
|
288
283
|
# Then try the record's show page
|
289
|
-
object_url(@this) ||
|
284
|
+
(!destroyed && object_url(@this)) ||
|
290
285
|
|
291
286
|
# Then the show page of the 'owning' object if there is one
|
292
|
-
(@this.class.default_dependent_on && object_url(@this.send(@this.class.default_dependent_on))) ||
|
287
|
+
(!destroyed && (@this.class.default_dependent_on && object_url(@this.send(@this.class.default_dependent_on)))) ||
|
293
288
|
|
294
289
|
# Last try - the index page for this model
|
295
290
|
object_url(@this.class) ||
|
@@ -312,21 +307,14 @@ module Hobo
|
|
312
307
|
|
313
308
|
|
314
309
|
def request_requires_pagination?
|
315
|
-
|
316
|
-
# like an image, if you clicked on an image link
|
317
|
-
request.format.in?(PAGINATE_FORMATS) || request.format.to_s =~ %r(image/)
|
310
|
+
request.format.not_in?(DONT_PAGINATE_FORMATS)
|
318
311
|
end
|
319
312
|
|
320
313
|
|
321
314
|
def find_or_paginate(finder, options)
|
322
315
|
options = options.reverse_merge(:paginate => request_requires_pagination?)
|
323
|
-
do_pagination = options.delete(:paginate)
|
316
|
+
do_pagination = options.delete(:paginate) && finder.respond_to?(:paginate)
|
324
317
|
|
325
|
-
if do_pagination && !finder.respond_to?(:paginate)
|
326
|
-
do_pagination = false
|
327
|
-
logger.warn "Hobo::ModelController: Pagination is not available. To enable, please install will_paginate or a duck-type compatible paginator"
|
328
|
-
end
|
329
|
-
|
330
318
|
if do_pagination
|
331
319
|
finder.paginate(options.reverse_merge(:page => params[:page] || 1))
|
332
320
|
else
|
@@ -388,7 +376,7 @@ module Hobo
|
|
388
376
|
if valid?
|
389
377
|
respond_to do |wants|
|
390
378
|
wants.html { redirect_to destination_after_submit }
|
391
|
-
wants.js { hobo_ajax_response || render(:
|
379
|
+
wants.js { hobo_ajax_response || render(:nothing => true) }
|
392
380
|
end
|
393
381
|
else
|
394
382
|
respond_to do |wants|
|
@@ -404,7 +392,7 @@ module Hobo
|
|
404
392
|
def hobo_update(*args, &b)
|
405
393
|
options = args.extract_options!
|
406
394
|
|
407
|
-
self.this
|
395
|
+
self.this = args.first || find_instance
|
408
396
|
changes = options[:attributes] || attribute_parameters
|
409
397
|
this.user_save_changes(current_user, changes)
|
410
398
|
|
@@ -428,7 +416,7 @@ module Hobo
|
|
428
416
|
wants.js do
|
429
417
|
if in_place_edit_field
|
430
418
|
# Decreasingly hacky support for the scriptaculous in-place-editor
|
431
|
-
new_val =
|
419
|
+
new_val = call_dryml_tag("view", :field => in_place_edit_field, :no_wrapper => true)
|
432
420
|
hobo_ajax_response(this, :new_field_value => new_val)
|
433
421
|
else
|
434
422
|
hobo_ajax_response(this)
|
@@ -451,7 +439,7 @@ module Hobo
|
|
451
439
|
|
452
440
|
def hobo_destroy(*args, &b)
|
453
441
|
options = args.extract_options!
|
454
|
-
self.this
|
442
|
+
self.this = args.first || find_instance
|
455
443
|
this.user_destroy(current_user)
|
456
444
|
flash[:notice] = "The #{model.name.titleize.downcase} was deleted" unless request.xhr?
|
457
445
|
destroy_response(&b)
|
@@ -461,7 +449,7 @@ module Hobo
|
|
461
449
|
def destroy_response(&b)
|
462
450
|
response_block(&b) or
|
463
451
|
respond_to do |wants|
|
464
|
-
wants.html { redirect_to(
|
452
|
+
wants.html { redirect_to destination_after_submit(this, true) }
|
465
453
|
wants.js { hobo_ajax_response || render(:nothing => true) }
|
466
454
|
end
|
467
455
|
end
|
@@ -490,9 +478,12 @@ module Hobo
|
|
490
478
|
end
|
491
479
|
|
492
480
|
|
493
|
-
def hobo_completions(finder)
|
481
|
+
def hobo_completions(attribute, finder, options={})
|
482
|
+
options = options.reverse_merge(:limit => 10, :param => :query)
|
483
|
+
finder = finder.limit(options[:limit]) unless finder.scope(:find, :limit)
|
484
|
+
finder = finder.send("#{attribute}_contains", params[options[:param]])
|
494
485
|
items = finder.find(:all)
|
495
|
-
render :text => "<ul>\n" + items.map {|i| "<li>#{i.send(
|
486
|
+
render :text => "<ul>\n" + items.map {|i| "<li>#{i.send(attribute)}</li>\n"}.join + "</ul>"
|
496
487
|
end
|
497
488
|
|
498
489
|
|
@@ -506,11 +497,11 @@ module Hobo
|
|
506
497
|
|
507
498
|
|
508
499
|
# --- Response helpers --- #
|
509
|
-
|
510
500
|
|
511
501
|
def permission_denied(error)
|
512
|
-
|
513
|
-
|
502
|
+
self.this = nil # Otherwise this gets sent user_view
|
503
|
+
if :permission_denied.in?(superclass.instance_methods)
|
504
|
+
super
|
514
505
|
else
|
515
506
|
respond_to do |wants|
|
516
507
|
wants.html do
|
@@ -529,8 +520,8 @@ module Hobo
|
|
529
520
|
|
530
521
|
|
531
522
|
def not_found(error)
|
532
|
-
if
|
533
|
-
|
523
|
+
if :not_found_response.in?(superclass.instance_methods)
|
524
|
+
super
|
534
525
|
elsif render_tag("not-found-page", {}, :status => 404)
|
535
526
|
# cool
|
536
527
|
else
|