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