Class: Card::Format
Constant Summary
collapse
- DEPRECATED_VIEWS =
{ view: :open, card: :open, line: :closed,
bare: :core, naked: :core }
- INCLUSION_MODES =
{ closed: :closed, closed_content: :closed, edit: :edit,
layout: :layout, new: :edit, setup: :edit,
normal: :normal, template: :template }
- @@registered =
[]
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#add_class(options, klass) ⇒ Object
-
#add_name_context(name = nil) ⇒ Object
-
#approved_view(view, args = {}) ⇒ Object
-
#canonicalize_view(view) ⇒ Object
-
#controller ⇒ Object
-
#current_view(view) ⇒ Object
-
#default_item_view ⇒ Object
-
#default_render_args(view, a = nil) ⇒ Object
-
#error_cardname ⇒ Object
-
#expand_main(opts) ⇒ Object
-
#fetch_nested_card(options) ⇒ Object
-
#focal? ⇒ Boolean
meaning the current card is the requested card.
-
#format_date(date, include_time = true) ⇒ Object
-
#get_content_object(content, opts) ⇒ Object
-
#get_context_names ⇒ Object
-
#get_inclusion_content(cardname) ⇒ Object
-
#get_inclusion_defaults(_nested_card) ⇒ Object
-
#hidden_view?(view, args) ⇒ Boolean
-
#include_set_format_modules ⇒ Object
-
#inclusion_defaults(nested_card) ⇒ Object
-
#initialize(card, opts = {}) ⇒ Format
constructor
-
#legacy_main_opts_tweaks!(opts) ⇒ Object
-
#main? ⇒ Boolean
-
#method_missing(method, *opts, &proc) ⇒ Object
-
#nest(nested_card, opts = {}) ⇒ Object
-
#nest_arg_visibility(view, args) ⇒ Object
-
#ok?(task) ⇒ Boolean
-
#ok_view(view, args = {}) ⇒ Object
-
#params ⇒ Object
-
#parse_view_visibility(val) ⇒ Object
-
#permitted_view(view, args) ⇒ Object
-
#prepare_nest(opts) ⇒ Object
-
#process_content(override_content = nil, opts = {}) ⇒ Object
-
#process_content_object(override_content = nil, opts = {}) ⇒ Object
-
#render(view, args = {}) ⇒ Object
-
#rendering_error(_exception, view) ⇒ Object
-
#rescue_view(e, view) ⇒ Object
-
#session ⇒ Object
-
#show_view?(view, args) ⇒ Boolean
-
#showname(title = nil) ⇒ Object
-
#subformat(subcard) ⇒ Object
————- Sub Format and Inclusion Processing ————.
-
#tagged(view, tag) ⇒ Object
-
#template ⇒ Object
-
#unique_id ⇒ Object
-
#view_for_unknown(_view, _args) ⇒ Object
-
#view_in_closed_mode(homeview, nested_card) ⇒ Object
-
#view_in_edit_mode(homeview, nested_card) ⇒ Object
-
#view_method(view, args) ⇒ Object
-
#with_inclusion_mode(mode) ⇒ Object
-
#with_name_context(name) ⇒ Object
-
#wrap_main(content) ⇒ Object
Methods included from Location
#card_path, #card_url, #page_path
Constructor Details
#initialize(card, opts = {}) ⇒ Format
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/card/format.rb', line 86
def initialize card, opts={}
unless (@card = card)
raise Card::Error, 'format initialized without card'
end
opts.each do |key, value|
instance_variable_set "@#{key}", value
end
@mode ||= :normal
@root ||= self
@depth ||= 0
@context_names = get_context_names
include_set_format_modules
self
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *opts, &proc) ⇒ Object
185
186
187
188
189
190
191
192
193
194
195
196
197
|
# File 'lib/card/format.rb', line 185
def method_missing method, *opts, &proc
if method =~ /(_)?(optional_)?render(_(\w+))?/
view = $3 ? $4 : opts.shift
args = opts[0] ? opts.shift.clone : {}
args.merge!(optional: true, default_visibility: opts.shift) if $2
args[:skip_permissions] = true if $1
render view, args
else
proc = proc { |*a| raw yield *a } if proc
response = root.template.send method, *opts, &proc
response.is_a?(String) ? root.template.raw(response) : response
end
end
|
Instance Attribute Details
Returns the value of attribute card.
21
22
23
|
# File 'lib/card/format.rb', line 21
def card
@card
end
|
#error_status ⇒ Object
Returns the value of attribute error_status.
22
23
24
|
# File 'lib/card/format.rb', line 22
def error_status
@error_status
end
|
Returns the value of attribute form.
22
23
24
|
# File 'lib/card/format.rb', line 22
def form
@form
end
|
#inclusion_opts ⇒ Object
Returns the value of attribute inclusion_opts.
22
23
24
|
# File 'lib/card/format.rb', line 22
def inclusion_opts
@inclusion_opts
end
|
#main_opts ⇒ Object
Returns the value of attribute main_opts.
21
22
23
|
# File 'lib/card/format.rb', line 21
def main_opts
@main_opts
end
|
Returns the value of attribute parent.
21
22
23
|
# File 'lib/card/format.rb', line 21
def parent
@parent
end
|
Returns the value of attribute root.
21
22
23
|
# File 'lib/card/format.rb', line 21
def root
@root
end
|
Class Method Details
38
39
40
41
42
43
44
45
|
# File 'lib/card/format.rb', line 38
def view, opts
return unless opts.present?
[:perms, :error_code, :denial, :closed].each do |varname|
class_var = send varname
class_var[view] = opts.delete(varname) if opts[varname]
end
view, opts
end
|
47
48
49
50
51
52
53
54
|
# File 'lib/card/format.rb', line 47
def view, opts
tags = opts.delete :tags
return unless tags
Array.wrap(tags).each do |tag|
view_tags[view] ||= {}
view_tags[view][tag] = true
end
end
|
71
72
73
74
75
76
77
|
# File 'lib/card/format.rb', line 71
def format_ancestry
ancestry = [self]
unless self == Card::Format
ancestry = ancestry + superclass.format_ancestry
end
ancestry
end
|
31
32
33
34
35
36
|
# File 'lib/card/format.rb', line 31
def format_class_name format
format = format.to_s
format = '' if format == 'base'
format = @@aliases[format] if @@aliases[format]
"#{format.camelize}Format"
end
|
.max_depth ⇒ Object
79
80
81
|
# File 'lib/card/format.rb', line 79
def max_depth
Card.config.max_depth
end
|
.new(card, opts = {}) ⇒ Object
56
57
58
59
60
61
62
63
64
|
# File 'lib/card/format.rb', line 56
def new card, opts={}
if self != Format
super
else
format = opts[:format] || :html
klass = Card.const_get format_class_name(format)
self == klass ? super : klass.new(card, opts)
end
end
|
.register(format) ⇒ Object
27
28
29
|
# File 'lib/card/format.rb', line 27
def register format
@@registered << format.to_s
end
|
.tagged(view, tag) ⇒ Object
66
67
68
69
|
# File 'lib/card/format.rb', line 66
def tagged view, tag
return unless view && tag && (view_tags = @@view_tags[view.to_sym])
view_tags[tag.to_sym]
end
|
Instance Method Details
#add_class(options, klass) ⇒ Object
562
563
564
|
# File 'lib/card/format.rb', line 562
def add_class options, klass
options[:class] = [options[:class], klass].flatten.compact * ' '
end
|
#add_name_context(name = nil) ⇒ Object
581
582
583
584
585
|
# File 'lib/card/format.rb', line 581
def add_name_context name=nil
name ||= card.name
@context_names += name.to_name.part_names
@context_names.uniq!
end
|
#approved_view(view, args = {}) ⇒ Object
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
|
# File 'lib/card/format.rb', line 358
def approved_view view, args={}
case
when @depth >= Card.config.max_depth
:too_deep
when @@perms[view] == :none
view
when args.delete(:skip_permissions)
view
when !card.known? && !tagged(view, :unknown_ok)
view_for_unknown view, args
else
permitted_view view, args
end
end
|
#canonicalize_view(view) ⇒ Object
410
411
412
413
414
|
# File 'lib/card/format.rb', line 410
def canonicalize_view view
return if view.blank?
view_key = view.to_viewname.key.to_sym
DEPRECATED_VIEWS[view_key] || view_key
end
|
#controller ⇒ Object
140
141
142
|
# File 'lib/card/format.rb', line 140
def controller
Env[:controller] ||= CardController.new
end
|
#current_view(view) ⇒ Object
297
298
299
300
301
302
303
|
# File 'lib/card/format.rb', line 297
def current_view view
old_view = @current_view
@current_view = view
yield
ensure
@current_view = old_view
end
|
#default_item_view ⇒ Object
554
555
556
|
# File 'lib/card/format.rb', line 554
def default_item_view
:name
end
|
#default_render_args(view, a = nil) ⇒ Object
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
# File 'lib/card/format.rb', line 265
def default_render_args view, a=nil
args =
case a
when nil then {}
when Hash then a.clone
when Array then a[0].merge a[1]
else raise Card::Error, "bad render args: #{a}"
end
default_method = "default_#{view}_args"
if respond_to? default_method
send default_method, args
end
args
end
|
#error_cardname ⇒ Object
305
306
307
|
# File 'lib/card/format.rb', line 305
def error_cardname
card && card.name.present? ? card.name : 'unknown card'
end
|
#expand_main(opts) ⇒ Object
451
452
453
454
455
456
457
458
459
460
461
|
# File 'lib/card/format.rb', line 451
def expand_main opts
opts.merge! root.main_opts if root.main_opts
legacy_main_opts_tweaks! opts
with_inclusion_mode :normal do
@mainline = true
result = wrap_main nest(root.card, opts)
@mainline = false
result
end
end
|
#fetch_nested_card(options) ⇒ Object
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
|
# File 'lib/card/format.rb', line 538
def fetch_nested_card options
args = { name: options[:inc_name], type: options[:type], supercard: card }
args.delete(:supercard) if options[:inc_name].strip.blank?
if options[:inc_name] =~ /^_main\+/
args[:name] = args[:name].gsub /^_main\+/, '+'
args[:supercard] = root.card
end
if (content = get_inclusion_content options[:inc_name])
args[:content] = content
end
Card.fetch options[:inc_name], new: args
end
|
#focal? ⇒ Boolean
meaning the current card is the requested card
168
169
170
171
172
173
174
|
# File 'lib/card/format.rb', line 168
def focal? if Env.ajax?
@depth == 0
else
main?
end
end
|
570
571
572
573
574
575
576
577
578
579
|
# File 'lib/card/format.rb', line 570
def format_date date, include_time=true
if include_time
DateTime.new(
date.year, date.mon, date.day, date.hour, date.min, date.sec
).strftime('%B %e, %Y %H:%M:%S')
else
DateTime.new(date.year, date.mon, date.day).strftime('%B %e, %Y')
end
end
|
#get_content_object(content, opts) ⇒ Object
340
341
342
343
344
345
346
|
# File 'lib/card/format.rb', line 340
def get_content_object content, opts
if content.is_a? Content
content
else
Content.new content, self, opts.delete(:content_opts)
end
end
|
#get_context_names ⇒ Object
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/card/format.rb', line 103
def get_context_names
case
when @context_names
part_keys = @card.cardname.part_names.map &:key
@context_names.reject { |n| !part_keys.include? n.key }
when params[:slot]
context_name_list = params[:slot][:name_context].to_s
context_name_list.split(',').map &:to_name
else
[]
end
end
|
#get_inclusion_content(cardname) ⇒ Object
527
528
529
530
531
532
533
534
535
536
|
# File 'lib/card/format.rb', line 527
def get_inclusion_content cardname
content = params[cardname.to_s.tr('+', '_')]
p = params['subcards']
if p && (card_params = p[cardname.to_s])
content = card_params['content']
end
content if content.present? end
|
#get_inclusion_defaults(_nested_card) ⇒ Object
132
133
134
|
# File 'lib/card/format.rb', line 132
def get_inclusion_defaults _nested_card
{ view: :name }
end
|
#hidden_view?(view, args) ⇒ Boolean
227
228
229
|
# File 'lib/card/format.rb', line 227
def hidden_view? view, args
args.delete(:optional) && !show_view?(view, args)
end
|
116
117
118
119
120
121
122
|
# File 'lib/card/format.rb', line 116
def include_set_format_modules
self.class.format_ancestry.reverse_each do |klass|
card.set_format_modules(klass).each do |m|
singleton_class.send :include, m
end
end
end
|
#inclusion_defaults(nested_card) ⇒ Object
124
125
126
127
128
129
130
|
# File 'lib/card/format.rb', line 124
def inclusion_defaults nested_card
@inclusion_defaults ||= begin
defaults = get_inclusion_defaults(nested_card).clone
defaults.merge! @inclusion_opts if @inclusion_opts
defaults
end
end
|
#legacy_main_opts_tweaks!(opts) ⇒ Object
463
464
465
466
467
468
469
470
471
|
# File 'lib/card/format.rb', line 463
def legacy_main_opts_tweaks! opts
if (val = params[:size]) && val.present?
opts[:size] = val.to_sym
end
if (val = params[:item]) && val.present?
opts[:items] = (opts[:items] || {}).reverse_merge view: val.to_sym
end
end
|
#main? ⇒ Boolean
164
165
166
|
# File 'lib/card/format.rb', line 164
def main?
@depth == 0
end
|
#nest(nested_card, opts = {}) ⇒ Object
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
|
# File 'lib/card/format.rb', line 477
def nest nested_card, opts={}
opts.delete_if { |_k, v| v.nil? }
opts.reverse_merge! inclusion_defaults(nested_card)
sub = nil
if opts[:inc_name] =~ /^_(self)?$/
sub = self
else
sub = subformat nested_card
sub.inclusion_opts = opts[:items] ? opts[:items].clone : {}
end
view = canonicalize_view opts.delete :view
opts[:home_view] = [:closed, :edit].member?(view) ? :open : view
view =
case @mode
when :edit then view_in_edit_mode(view, nested_card)
when :template then :template_rule
when :closed then view_in_closed_mode(view, nested_card)
else view
end
sub.optional_render view, opts
end
|
#nest_arg_visibility(view, args) ⇒ Object
249
250
251
252
253
254
|
# File 'lib/card/format.rb', line 249
def nest_arg_visibility view, args
[:show, :hide].each do |setting|
return setting if parse_view_visibility(args[setting]).member?(view)
end
false
end
|
#ok?(task) ⇒ Boolean
398
399
400
401
402
403
|
# File 'lib/card/format.rb', line 398
def ok? task
task = :create if task == :update && card.new_card?
@ok ||= {}
@ok[task] = card.ok? task if @ok[task].nil?
@ok[task]
end
|
#ok_view(view, args = {}) ⇒ Object
348
349
350
351
352
353
354
355
356
|
# File 'lib/card/format.rb', line 348
def ok_view view, args={}
return view if args.delete :skip_permissions
approved_view = approved_view view, args
args[:denied_view] = view if approved_view != view
if focal? && (error_code = @@error_code[approved_view])
root.error_status = error_code
end
approved_view
end
|
136
137
138
|
# File 'lib/card/format.rb', line 136
def params
Env.params
end
|
#parse_view_visibility(val) ⇒ Object
256
257
258
259
260
261
262
263
|
# File 'lib/card/format.rb', line 256
def parse_view_visibility val
case val
when NilClass then []
when Array then val
when String then val.split(/[\s,]+/)
else raise Card::Error, "bad show/hide argument: #{val}"
end.map { |view| canonicalize_view view }
end
|
#permitted_view(view, args) ⇒ Object
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
|
# File 'lib/card/format.rb', line 382
def permitted_view view, args
perms_required = @@perms[view] || :read
args[:denied_task] =
if Proc === perms_required
:read if !(perms_required.call self) else
[perms_required].flatten.find { |task| !ok? task }
end
if args[:denied_task]
@@denial[view] || :denial
else
view
end
end
|
#prepare_nest(opts) ⇒ Object
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
|
# File 'lib/card/format.rb', line 429
def prepare_nest opts
@char_count ||= 0
opts ||= {}
case
when opts.has_key?(:comment)
opts[:comment]
when @mode == :closed && @char_count > Card.config.max_char_count
''
when opts[:inc_name] == '_main' && show_layout? && @depth == 0
expand_main opts
else
result = nest fetch_nested_card(opts), opts
@char_count += result.length if @mode == :closed && result
result
end
end
|
#process_content(override_content = nil, opts = {}) ⇒ Object
328
329
330
|
# File 'lib/card/format.rb', line 328
def process_content override_content=nil, opts={}
process_content_object(override_content, opts).to_s
end
|
#process_content_object(override_content = nil, opts = {}) ⇒ Object
332
333
334
335
336
337
338
|
# File 'lib/card/format.rb', line 332
def process_content_object override_content=nil, opts={}
content = override_content || render_raw || ''
content_object = get_content_object content, opts
content_object.process_each_chunk do |chunk_opts|
prepare_nest chunk_opts.merge(opts) { yield }
end
end
|
#render(view, args = {}) ⇒ Object
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
# File 'lib/card/format.rb', line 203
def render view, args={}
view = canonicalize_view view
return if hidden_view? view, args
view = ok_view view, args
current_view(view) do
args = default_render_args view, args
with_inclusion_mode view do
Card::ViewCache.fetch(self, view, args) do
method = view_method view, args
method.arity == 0 ? method.call : method.call(args)
end
end
end
rescue => e
rescue_view e, view
end
|
#rendering_error(_exception, view) ⇒ Object
309
310
311
|
# File 'lib/card/format.rb', line 309
def rendering_error _exception, view
"Error rendering: #{error_cardname} (#{view} view)"
end
|
#rescue_view(e, view) ⇒ Object
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
# File 'lib/card/format.rb', line 281
def rescue_view e, view
if Rails.env =~ /^cucumber|test$/
raise e
else
Rails.logger.info "\nError rendering #{error_cardname} / #{view}: "\
"#{e.class} : #{e.message}"
Card::Error.current = e
card.notable_exception_raised
if (debug = Card[:debugger]) && debug.content == 'on'
raise e
else
rendering_error e, view
end
end
end
|
144
145
146
|
# File 'lib/card/format.rb', line 144
def session
Env.session
end
|
#show_view?(view, args) ⇒ Boolean
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
# File 'lib/card/format.rb', line 231
def show_view? view, args
default = args.delete(:default_visibility) || :show api_option = args["optional_#{view}".to_sym]
case
when api_option == :always then true
when api_option == :never then false
else
contextual_setting = nest_arg_visibility(view, args) || api_option
case contextual_setting
when :show then true
when :hide then false
else default == :show
end
end
end
|
#showname(title = nil) ⇒ Object
148
149
150
151
152
153
154
|
# File 'lib/card/format.rb', line 148
def showname title=nil
if title
title.to_name.to_absolute_name(card.cardname).to_show *@context_names
else
@showname ||= card.cardname.to_show *@context_names
end
end
|
————- Sub Format and Inclusion Processing ————
317
318
319
320
321
322
323
324
325
326
|
# File 'lib/card/format.rb', line 317
def subformat subcard
subcard = Card.fetch(subcard, new: {}) if subcard.is_a?(String)
self.class.new subcard,
parent: self, depth: @depth + 1, root: @root,
context_names: @context_names, mode: @mode,
mainline: @mainline, form: @form
end
|
#tagged(view, tag) ⇒ Object
378
379
380
|
# File 'lib/card/format.rb', line 378
def tagged view, tag
self.class.tagged view, tag
end
|
176
177
178
179
180
181
182
183
|
# File 'lib/card/format.rb', line 176
def template
@template ||= begin
c = controller
t = ActionView::Base.new c.class.view_paths, { _routes: c._routes }, c
t.extend c.class._helpers
t
end
end
|
#unique_id ⇒ Object
566
567
568
|
# File 'lib/card/format.rb', line 566
def unique_id
"#{card.key}-#{Time.now.to_i}-#{rand(3)}"
end
|
#view_for_unknown(_view, _args) ⇒ Object
405
406
407
408
|
# File 'lib/card/format.rb', line 405
def view_for_unknown _view, _args
focal? ? :not_found : :missing
end
|
#view_in_closed_mode(homeview, nested_card) ⇒ Object
516
517
518
519
520
521
522
523
524
525
|
# File 'lib/card/format.rb', line 516
def view_in_closed_mode homeview, nested_card
approved_view = @@closed[homeview]
case
when approved_view == true then homeview
when @@error_code[homeview] then homeview
when approved_view then approved_view
when !nested_card.known? then :closed_missing
else :closed_content
end
end
|
#view_in_edit_mode(homeview, nested_card) ⇒ Object
507
508
509
510
511
512
513
514
|
# File 'lib/card/format.rb', line 507
def view_in_edit_mode homeview, nested_card
not_in_form =
@@perms[homeview] == :none || nested_card.structure || nested_card.key.blank?
not_in_form ? :blank : :edit_in_form
end
|
#view_method(view, args) ⇒ Object
220
221
222
223
224
225
|
# File 'lib/card/format.rb', line 220
def view_method view, args
method "_view_#{view}"
rescue
args[:unsupported_view] = view
method '_view_unsupported_view'
end
|
#with_inclusion_mode(mode) ⇒ Object
416
417
418
419
420
421
422
423
424
425
426
427
|
# File 'lib/card/format.rb', line 416
def with_inclusion_mode mode
if (switch_mode = INCLUSION_MODES[mode]) && @mode != switch_mode
old_mode, @mode = @mode, switch_mode
@inclusion_defaults = nil
end
result = yield
if old_mode
@inclusion_defaults = nil
@mode = old_mode
end
result
end
|
#with_name_context(name) ⇒ Object
156
157
158
159
160
161
162
|
# File 'lib/card/format.rb', line 156
def with_name_context name
old_context = @context_names
add_name_context name
result = yield
@context_names = old_context
result
end
|
#wrap_main(content) ⇒ Object
473
474
475
|
# File 'lib/card/format.rb', line 473
def wrap_main content
content end
|