Class: AutoForme::Action

Inherits:
Object
  • Object
show all
Defined in:
lib/autoforme/action.rb

Overview

Represents an action on a model in response to a web request.

Constant Summary collapse

ALL_SUPPORTED_ACTIONS =

Array of strings for all action types currently supported

%w'new create show edit update delete destroy browse search mtm_edit mtm_update association_links autocomplete'.freeze
NORMALIZED_ACTION_MAP =

Map of regular type symbols to normalized type symbols

{:create=>:new, :update=>:edit, :destroy=>:delete, :mtm_update=>:mtm_edit}
TITLE_MAP =

Map of type symbols to HTML titles

{:new=>'New', :show=>'Show', :edit=>'Edit', :delete=>'Delete', :browse=>'Browse', :search=>'Search', :mtm_edit=>'Many To Many Edit'}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, request) ⇒ Action

Creates a new action for the model and request. This action is not usable unless supported? is called first and it returns true.



34
35
36
37
# File 'lib/autoforme/action.rb', line 34

def initialize(model, request)
  @model = model
  @request = request
end

Instance Attribute Details

#model ⇒ Object (readonly)

The AutoForme::Model instance related to the current action



5
6
7
# File 'lib/autoforme/action.rb', line 5

def model
  @model
end

#normalized_type ⇒ Object (readonly)

The normalized type symbol related to the current action, so that paired actions such as new and create both use :new.



9
10
11
# File 'lib/autoforme/action.rb', line 9

def normalized_type
  @normalized_type
end

#params_association ⇒ Object (readonly)

An association symbol for the current related association.



12
13
14
# File 'lib/autoforme/action.rb', line 12

def params_association
  @params_association
end

#request ⇒ Object (readonly)

The AutoForme::Request instance related to the current action



15
16
17
# File 'lib/autoforme/action.rb', line 15

def request
  @request
end

#title ⇒ Object (readonly)

An string suitable for use as the HTML title on the displayed page



18
19
20
# File 'lib/autoforme/action.rb', line 18

def title
  @title
end

#type ⇒ Object (readonly)

The type symbols related to the current action (e.g. :new, :create).



21
22
23
# File 'lib/autoforme/action.rb', line 21

def type
  @type
end

Instance Method Details

If the framework contains the associated model class and that supports browsing, return a link to the associated browse page, otherwise, just return the name.



566
567
568
569
570
571
572
573
# File 'lib/autoforme/action.rb', line 566

def association_class_link(mc, assoc)
  assoc_name = humanize(assoc)
  if mc && mc.supported_action?(:browse, request)
    "<a href=\"#{base_url_for("#{mc.link}/browse")}\">#{assoc_name}</a>"
  else
    assoc_name
  end
end

For the given associated object, if the framework contains the associated model class, and that supports the type of action we are doing, return a link to the associated action page.



578
579
580
581
582
583
584
585
586
587
588
# File 'lib/autoforme/action.rb', line 578

def association_link(mc, assoc_obj)
  if mc
    t = mc.object_display_name(:association, request, assoc_obj)
    if mc.supported_action?(type, request)
      t = "<a href=\"#{base_url_for("#{mc.link}/#{type}/#{mc.primary_key_value(assoc_obj)}")}\">#{t}</a>"
    end
    t
  else
    model.default_object_display_name(assoc_obj)
  end
end

HTML fragment for the list of association links, allowing quick access to associated models and objects.



513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/autoforme/action.rb', line 513

def association_link_list(obj)
  assocs = model.association_links_for(type, request) 
  return if assocs.empty?
  read_only = type == :show
  t = '<h3 class="associated_records_header">Associated Records</h3>'
  t << "<ul class='association_links'>\n"
  assocs.each do |assoc|
    mc = model.associated_model_class(assoc)
    t << "<li>"
    t << association_class_link(mc, assoc)
    t << "\n "

    case model.association_type(assoc)
    when :one
      if assoc_obj = obj.send(assoc)
        t << " - "
        t << association_link(mc, assoc_obj)
      end
      assoc_objs = []
    when :edit
      if !read_only && model.supported_mtm_edit?(assoc.to_s, request)
        t << "(<a href=\"#{url_for("mtm_edit/#{model.primary_key_value(obj)}?association=#{assoc}")}\">associate</a>)"
      end
      assoc_objs = obj.send(assoc)
    when :new
      if !read_only && mc && mc.supported_action?(:new, request)
        params = model.associated_new_column_values(obj, assoc).map do |col, value|
          "#{mc.link}%5b#{col}%5d=#{value}"
        end
        t << "(<a href=\"#{base_url_for("#{mc.link}/new?#{params.join('&amp;')}")}\">create</a>)"
      end
      assoc_objs = obj.send(assoc)
    else
      assoc_objs = []
    end

    unless assoc_objs.empty?
      t << "<ul>\n"
      assoc_objs.each do |assoc_obj|
        t << "<li>"
        t << association_link(mc, assoc_obj)
        t << "</li>"
      end
      t << "</ul>"
    end

    t << "</li>"
  end
  t << "</ul>"
end

HTML fragment containing the association links for the given object, or a link to lazily load them if configured. Also contains the inline mtm_edit forms when editing.



502
503
504
505
506
507
508
509
510
# File 'lib/autoforme/action.rb', line 502

def association_links(obj)
  if model.lazy_load_association_links?(type, request) && normalized_type != :association_links && request.params['associations'] != 'show'
    "<div id='lazy_load_association_links' data-object='#{model.primary_key_value(obj)}' data-type='#{type}'><a href=\"#{url_for("#{type}/#{model.primary_key_value(obj)}?associations=show")}\">Show Associations</a></div>"
  elsif type == :show
    association_link_list(obj).to_s
  else
    "#{inline_mtm_edit_forms(obj)}#{association_link_list(obj)}"
  end
end

#base_url_for(page) ⇒ Object

A path for the given page tied to the framework, but not the current model. Used for linking to other models in the same framework.



103
104
105
# File 'lib/autoforme/action.rb', line 103

def base_url_for(page)
  "#{request.path}#{model.framework.prefix}/#{page}"
end

#column_label_for(type, request, model, column) ⇒ Object

The label to use for the given column.



168
169
170
171
172
173
# File 'lib/autoforme/action.rb', line 168

def column_label_for(type, request, model, column)
  unless label = model.column_options_for(type, request, column)[:label]
    label = humanize(column)
  end
  label
end

#column_options_for(type, request, obj, column) ⇒ Object

The options to use for the given column, which will be passed to Forme::Form#input.



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/autoforme/action.rb', line 155

def column_options_for(type, request, obj, column)
  opts = model.column_options_for(type, request, column)
  if opts[:class] == 'autoforme_autocomplete'
    if type == :show
      opts[:value] = model.column_value(type, request, obj, column)
    elsif key = obj.send(model.association_key(column))
      opts[:value] = "#{key} - #{model.column_value(type, request, obj, column)}"
    end
  end
  opts
end

#edit_page(obj) ⇒ Object

The page to use when editing the object.



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/autoforme/action.rb', line 315

def edit_page(obj)
  page do
    t = Forme.form(obj, form_attributes(:action=>url_for("update/#{model.primary_key_value(obj)}")), form_opts) do |f|
      model.columns_for(:edit, request).each do |column|
        f.input(column, column_options_for(:edit, request, obj, column))
      end
      f.button(:value=>'Update', :class=>'btn btn-primary')
    end.to_s
    if model.supported_action?(:delete, request)
      t << Forme.form(form_attributes(:action=>url_for("delete/#{model.primary_key_value(obj)}")), form_opts) do |f|
        f.button(:value=>'Delete', :class=>'btn btn-danger')
      end.to_s
    end
    t << association_links(obj)
  end
end

#form_attributes(attrs) ⇒ Object

Merge the model's form attributes into the given form attributes, yielding the attributes to use for the form.



221
222
223
# File 'lib/autoforme/action.rb', line 221

def form_attributes(attrs)
  attrs.merge(model.form_attributes_for(type, request))
end

#form_opts ⇒ Object

Options to use for the form. If the form uses POST, automatically adds the CSRF token.



210
211
212
213
214
215
216
217
# File 'lib/autoforme/action.rb', line 210

def form_opts
  opts = model.form_options_for(type, request).dup
  hidden_tags = opts[:hidden_tags] = []
  if csrf = request.csrf_token_hash
    hidden_tags << lambda{|tag| csrf if tag.attr[:method].to_s.upcase == 'POST'}
  end
  opts
end

#h(s) ⇒ Object

Convert input to a string adn HTML escape it.



86
87
88
# File 'lib/autoforme/action.rb', line 86

def h(s)
  Rack::Utils.escape_html(s.to_s)
end

#handle ⇒ Object

Handle the current action, returning an HTML string containing the page content, or redirecting.



143
144
145
146
# File 'lib/autoforme/action.rb', line 143

def handle
  model.before_action_hook(type, request)
  send("handle_#{type}")
end

Handle association_links action by returning an HTML fragment of association links.



487
488
489
490
491
# File 'lib/autoforme/action.rb', line 487

def handle_association_links
  @type = @normalized_type = @subtype
  obj = model.with_pk(@type, request, request.id)
  association_links(obj)
end

#handle_autocomplete ⇒ Object

Handle autocomplete action by returning a string with one line per model object.



494
495
496
497
498
# File 'lib/autoforme/action.rb', line 494

def handle_autocomplete
  unless (query = request.params['q'].to_s).empty?
    model.autocomplete(:type=>@subtype, :request=>request, :association=>params_association, :query=>query, :exclude=>request.params['exclude']).join("\n")
  end
end

#handle_browse ⇒ Object

Handle browse action by showing a table containing model objects.



403
404
405
# File 'lib/autoforme/action.rb', line 403

def handle_browse
  table_page(*model.browse(type, request))
end

#handle_create ⇒ Object

Handle the create action by creating a new model object.



245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/autoforme/action.rb', line 245

def handle_create
  obj = model.new(nil, request)
  model.set_fields(obj, :new, request, model_params)
  model.hook(:before_create, request, obj)
  if model.save(obj)
    model.hook(:after_create, request, obj)
    request.set_flash_notice("Created #{model.class_name}")
    redirect(:new, obj)
  else
    request.set_flash_now_error("Error Creating #{model.class_name}")
    new_page(obj)
  end
end

#handle_delete ⇒ Object

Handle the edit action by showing a list page if there is no model object selected, or a confirmation screen if there is one.



359
360
361
362
363
364
365
# File 'lib/autoforme/action.rb', line 359

def handle_delete
  if request.id
    handle_show
  else
    list_page(:delete, :form=>{:action=>url_for('delete')})
  end
end

#handle_destroy ⇒ Object

Handle the destroy action by destroying the model object.



368
369
370
371
372
373
374
375
# File 'lib/autoforme/action.rb', line 368

def handle_destroy
  obj = model.with_pk(normalized_type, request, request.id)
  model.hook(:before_destroy, request, obj)
  model.destroy(obj)
  model.hook(:after_destroy, request, obj)
  request.set_flash_notice("Deleted #{model.class_name}")
  redirect(:delete, obj)
end

#handle_edit ⇒ Object

Handle the edit action by showing a list page if there is no model object selected, or the edit page if there is one.



333
334
335
336
337
338
339
340
341
# File 'lib/autoforme/action.rb', line 333

def handle_edit
  if request.id
    obj = model.with_pk(normalized_type, request, request.id)
    model.hook(:before_edit, request, obj)
    edit_page(obj)
  else
    list_page(:edit)
  end
end

#handle_mtm_edit ⇒ Object

Handle the mtm_edit action by showing a list page if there is no model object selected, a list of associations for that model if there is a model object but no association selected, or a mtm_edit form if there is a model object and association selected.



426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/autoforme/action.rb', line 426

def handle_mtm_edit
  if id = request.id
    obj = model.with_pk(:edit, request, request.id)
    unless assoc = params_association
      options = model.mtm_association_select_options(request)
      if options.length == 1
        assoc = options.first
      end
    end
    if assoc
      page do
        t = "<h2>Edit #{humanize(assoc)} for #{h model.object_display_name(type, request, obj)}</h2>"
        t << Forme.form(obj, form_attributes(:action=>url_for("mtm_update/#{model.primary_key_value(obj)}?association=#{assoc}")), form_opts) do |f|
          opts = model.column_options_for(:mtm_edit, request, assoc)
          add_opts = opts[:add] ? opts.merge(opts.delete(:add)) : opts
          remove_opts = opts[:remove] ? opts.merge(opts.delete(:remove)) : opts
          add_opts = {:name=>'add[]', :id=>'add', :label=>'Associate With'}.merge(add_opts)
          if model.association_autocomplete?(assoc, request)
            f.input(assoc, {:type=>'text', :class=>'autoforme_autocomplete', :attr=>{'data-type'=>'association', 'data-column'=>assoc, 'data-exclude'=>model.primary_key_value(obj)}, :value=>''}.merge(add_opts))
          else
            f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj)}.merge(add_opts))
          end
          f.input(assoc, {:name=>'remove[]', :id=>'remove', :label=>'Disassociate From', :dataset=>model.associated_mtm_objects(request, assoc, obj), :value=>[]}.merge(remove_opts))
          f.button(:value=>'Update', :class=>'btn btn-primary')
        end.to_s
      end
    else
      page do
        Forme.form(form_attributes(:action=>"mtm_edit/#{model.primary_key_value(obj)}"), form_opts) do |f|
          f.input(:select, :options=>options, :name=>'association', :id=>'association', :label=>'Association', :add_blank=>true)
          f.button(:value=>'Edit', :class=>'btn btn-primary')
        end
      end
    end
  else
    list_page(:edit, :form=>{})
  end
end

#handle_mtm_update ⇒ Object

Handle mtm_update action by updating the related many to many association. For ajax requests, return an HTML fragment to update the page, otherwise redirect to the appropriate form.



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/autoforme/action.rb', line 467

def handle_mtm_update
  obj = model.with_pk(:edit, request, request.id)
  assoc = params_association
  assoc_obj = model.mtm_update(request, assoc, obj, request.params['add'], request.params['remove'])
  request.set_flash_notice("Updated #{assoc} association for #{model.class_name}") unless request.xhr?
  if request.xhr?
    if add = request.params['add']
      @type = :edit
      mtm_edit_remove(assoc, model.associated_model_class(assoc), obj, assoc_obj)
    else
      "<option value=\"#{model.primary_key_value(assoc_obj)}\">#{model.associated_object_display_name(assoc, request, assoc_obj)}</option>"
    end
  elsif request.params['redir'] == 'edit'
    redirect(:edit, obj)
  else
    redirect(:mtm_edit, obj)
  end
end

#handle_new ⇒ Object

Handle the new action by always showing the new form.



238
239
240
241
242
# File 'lib/autoforme/action.rb', line 238

def handle_new
  obj = model.new(request.params[model.link], request)
  model.hook(:before_new, request, obj)
  new_page(obj)
end

#handle_search ⇒ Object

Handle browse action by showing a search form if no page is selected, or the correct page of search results if there is a page selected.



409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/autoforme/action.rb', line 409

def handle_search
  if request.id
    table_page(*model.search_results(normalized_type, request))
  else
    page do
      Forme.form(model.new(nil, request), form_attributes(:action=>url_for("search/1"), :method=>:get), form_opts) do |f|
        model.columns_for(:search_form, request).each do |column|
          f.input(column, {:name=>column, :id=>column}.merge(column_options_for(:search_form, request, f.obj, column)))
        end
        f.button(:value=>'Search', :class=>'btn btn-primary')
      end
    end
  end
end

#handle_show ⇒ Object

Handle the show action by showing a list page if there is no model object selected, or the show page if there is one.



306
307
308
309
310
311
312
# File 'lib/autoforme/action.rb', line 306

def handle_show
  if request.id
    show_page(model.with_pk(normalized_type, request, request.id))
  else
    list_page(:show)
  end
end

#handle_update ⇒ Object

Handle the update action by updating the current model object.



344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/autoforme/action.rb', line 344

def handle_update
  obj = model.with_pk(normalized_type, request, request.id)
  model.set_fields(obj, :edit, request, model_params)
  model.hook(:before_update, request, obj)
  if model.save(obj)
    model.hook(:after_update, request, obj)
    request.set_flash_notice("Updated #{model.class_name}")
    redirect(:edit, obj)
  else
    request.set_flash_now_error("Error Updating #{model.class_name}")
    edit_page(obj)
  end
end

#humanize(string) ⇒ Object

Convert the given object into a suitable human readable string.



149
150
151
152
# File 'lib/autoforme/action.rb', line 149

def humanize(string)
  string = string.to_s
  string.respond_to?(:humanize) ? string.humanize : string.gsub(/_/, " ").capitalize
end

#idempotent? ⇒ Boolean

Return whether the current action is an idempotent action.

Returns:

  • (Boolean)


91
92
93
# File 'lib/autoforme/action.rb', line 91

def idempotent?
  type == normalized_type
end

#inline_mtm_edit_forms(obj) ⇒ Object

HTML fragment used for the inline mtm_edit forms on the edit page.



591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'lib/autoforme/action.rb', line 591

def inline_mtm_edit_forms(obj)
  assocs = model.inline_mtm_assocs(request)
  return if assocs.empty?

  t = "<div class='inline_mtm_add_associations'>"
  assocs.each do |assoc|
    form_attr = form_attributes(:action=>url_for("mtm_update/#{model.primary_key_value(obj)}?association=#{assoc}&amp;redir=edit"), :class => 'mtm_add_associations', 'data-remove' => "##{assoc}_remove_list")
    t << Forme.form(obj, form_attr, form_opts) do |f|
      opts = model.column_options_for(:mtm_edit, request, assoc)
      add_opts = opts[:add] ? opts.merge(opts.delete(:add)) : opts.dup
      add_opts = {:name=>'add[]', :id=>"add_#{assoc}"}.merge(add_opts)
      if model.association_autocomplete?(assoc, request)
        f.input(assoc, {:type=>'text', :class=>'autoforme_autocomplete', :attr=>{'data-type'=>'association', 'data-column'=>assoc, 'data-exclude'=>model.primary_key_value(obj)}, :value=>''}.merge(add_opts))
      else
        f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj), :multiple=>false, :add_blank=>true}.merge(add_opts))
      end
      f.button(:value=>'Add', :class=>'btn btn-mini btn-primary')
    end.to_s
  end
  t << "</div>"
  t << "<div class='inline_mtm_remove_associations'><ul>"
  assocs.each do |assoc|
    mc = model.associated_model_class(assoc)
    t << "<li>"
    t << association_class_link(mc, assoc)
    t << "<ul id='#{assoc}_remove_list'>"
    obj.send(assoc).each do |assoc_obj|
      t << mtm_edit_remove(assoc, mc, obj, assoc_obj)
    end
    t << "</ul></li>"
  end
  t << "</ul></div>"
end

#list_page(type, opts = {}) ⇒ Object

Shared page used by show, edit, and delete actions that shows a list of available model objects (or an autocompleting box), and allows the user to choose one to act on.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/autoforme/action.rb', line 261

def list_page(type, opts={})
  page do
    form_attr = form_attributes(opts[:form] || {:action=>url_for(type)})
    Forme.form(form_attr, form_opts) do |f|
      input_opts = {:name=>'id', :id=>'id', :label=>model.class_name}
      if model.autocomplete_options_for(type, request)
        input_type = :text
        input_opts.merge!(:class=>'autoforme_autocomplete', :attr=>{'data-type'=>type})
      else
        input_type = :select
        input_opts.merge!(:options=>model.select_options(type, request), :add_blank=>true)
      end
      f.input(input_type, input_opts)
      f.button(:value=>type.to_s.capitalize, :class=>"btn btn-#{type == :delete ? 'danger' : 'primary'}")
    end
  end
end

#model_params ⇒ Object

Get request parameters for the model. Used when retrieving form values that use namespacing.



97
98
99
# File 'lib/autoforme/action.rb', line 97

def model_params
  request.params[model.params_name]
end

#mtm_edit_remove(assoc, mc, obj, assoc_obj) ⇒ Object

Line item containing form to remove the currently associated object.



626
627
628
629
630
631
632
633
634
# File 'lib/autoforme/action.rb', line 626

def mtm_edit_remove(assoc, mc, obj, assoc_obj)
  t = "<li>"
  t << association_link(mc, assoc_obj)
  form_attr = form_attributes(:action=>url_for("mtm_update/#{model.primary_key_value(obj)}?association=#{assoc}&amp;remove%5b%5d=#{model.primary_key_value(assoc_obj)}&amp;redir=edit"), :method=>'post', :class => 'mtm_remove_associations', 'data-add'=>"#add_#{assoc}")
  t << Forme.form(form_attr, form_opts) do |f|
    f.button(:value=>'Remove', :class=>'btn btn-mini btn-danger')
  end.to_s
  t << "</li>"
end

#new_page(obj, opts = {}) ⇒ Object

HTML content used for the new action



226
227
228
229
230
231
232
233
234
235
# File 'lib/autoforme/action.rb', line 226

def new_page(obj, opts={})
  page do
    Forme.form(obj, form_attributes(:action=>url_for("create")), form_opts) do |f|
      model.columns_for(:new, request).each do |column|
        f.input(column, column_options_for(:new, request, obj, column))
      end
      f.button(:value=>'Create', :class=>'btn btn-primary')
    end
  end
end

#page ⇒ Object

Yields and wraps the returned data in a header and footer for the page.



199
200
201
202
203
204
205
206
207
# File 'lib/autoforme/action.rb', line 199

def page
  html = ''
  html << (model.page_header_for(type, request) || tabs)
  html << "<div id='autoforme_content' data-url='#{url_for('')}'>"
  html << yield.to_s
  html << "</div>"
  html << model.page_footer_for(type, request).to_s
  html
end

#redirect(type, obj) ⇒ Object

Redirect to a page based on the type of action and the given object.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/autoforme/action.rb', line 118

def redirect(type, obj)
  if redir = model.redirect_for
    path = redir.call(obj, type, request)
  end

  unless path
    path = case type
    when :new, :delete
      type.to_s
    when :edit
      "edit/#{model.primary_key_value(obj)}"
    when :mtm_edit
      "mtm_edit/#{model.primary_key_value(obj)}?association=#{params_association}"
    else
      raise Error, "Unhandled redirect type: #{type.inspect}"
    end
    path = url_for(path)
  end

  request.redirect(path)
  nil
end

#show_page(obj) ⇒ Object

The page to use when displaying an object, always used as a confirmation screen when deleting an object.



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/autoforme/action.rb', line 280

def show_page(obj)
  page do
    t = ''
    f = Forme::Form.new(obj, :formatter=>:readonly, :wrapper=>:trtd)
    t << "<table class=\"#{model.table_class_for(:show, request)}\">"
    model.columns_for(type, request).each do |column|
      t << f.input(column, column_options_for(:show, request, obj, column)).to_s
    end
    t << '</table>'
    if type == :show && model.supported_action?(:edit, request)
      t << Forme.form(form_attributes(:action=>url_for("edit/#{model.primary_key_value(obj)}")), form_opts) do |f|
        f.button(:value=>'Edit', :class=>'btn btn-primary')
      end.to_s
    end
    if type == :delete
      t << Forme.form(form_attributes(:action=>url_for("destroy/#{model.primary_key_value(obj)}"), :method=>:post), form_opts) do |f|
        f.button(:value=>'Delete', :class=>'btn btn-danger')
      end.to_s
    else
      t << association_links(obj)
    end
    t
  end
end

#subtype ⇒ Object

The subtype of request, used for association_links and autocomplete actions.



113
114
115
# File 'lib/autoforme/action.rb', line 113

def subtype
  ((t = request.params['type']) && ALL_SUPPORTED_ACTIONS.include?(t) && t.to_sym) || :edit
end

#supported? ⇒ Boolean

Return true if the action is supported, and false otherwise. An action may not be supported if the type is not one of the supported types, or if an non-idemponent request is issued with get instead of post, or potentionally other reasons.

As a side-effect, this sets up additional state related to the request.

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/autoforme/action.rb', line 45

def supported?
  return false unless idempotent? || request.post?
  return false unless ALL_SUPPORTED_ACTIONS.include?(request.action_type)

  @type = request.action_type.to_sym
  @normalized_type = NORMALIZED_ACTION_MAP.fetch(@type, @type)

  case type
  when :mtm_edit
    return false unless model.supported_action?(type, request)
    if request.id && (assoc = request.params['association'])
      return false unless model.supported_mtm_edit?(assoc, request)
      @params_association = assoc.to_sym
    end

    @title = "#{model.class_name} - #{TITLE_MAP[type]}"
  when :mtm_update
    return false unless request.id && (assoc = request.params['association']) && model.supported_mtm_update?(assoc, request)
    @params_association = assoc.to_sym
  when :association_links
    @subtype = subtype
    return false unless model.supported_action?(@subtype, request)
  when :autocomplete
    if assoc = request.id
      return false unless model.association?(assoc)
      @params_association = assoc.to_sym
    end
    @subtype = subtype
    return false unless model.autocomplete_options_for(@subtype, request)
  else
    return false unless model.supported_action?(normalized_type, request)

    if title = TITLE_MAP[type]
      @title = "#{model.class_name} - #{title}"
    end
  end

  true
end

#tab_name(type) ⇒ Object

The name to give the tab for the given type.



187
188
189
190
191
192
193
194
195
196
# File 'lib/autoforme/action.rb', line 187

def tab_name(type)
  case type
  when :browse
    model.class_name
  when :mtm_edit
    'MTM'
  else
    type.to_s.capitalize
  end
end

#table_page(next_page, objs) ⇒ Object

Show page used for browse/search pages.



396
397
398
399
400
# File 'lib/autoforme/action.rb', line 396

def table_page(next_page, objs)
  page do
    Table.new(self, objs).to_s << table_pager(normalized_type, next_page)
  end
end

#table_pager(type, next_page) ⇒ Object

HTML fragment for the table pager, showing links to next page or previous page for browse/search forms.



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/autoforme/action.rb', line 378

def table_pager(type, next_page)
  html = '<ul class="pager">'
  page = request.id.to_i
  if page > 1
    html << "<li><a href=\"#{url_for("#{type}/#{page-1}?#{h request.query_string}")}\">Previous</a></li>"
  else
    html << '<li class="disabled"><a href="#">Previous</a></li>'
  end
  if next_page
    page = 1 if page < 1
    html << "<li><a href=\"#{url_for("#{type}/#{page+1}?#{h request.query_string}")}\">Next</a></li>"
  else
    html << '<li class="disabled"><a href="#">Next</a></li>'
  end
  html << "</ul>"
end

#tabs ⇒ Object

HTML fragment for the default page header, which uses tabs for each supported action.



176
177
178
179
180
181
182
183
184
# File 'lib/autoforme/action.rb', line 176

def tabs
  content = '<ul class="nav nav-tabs">'
  Model::DEFAULT_SUPPORTED_ACTIONS.each do |action_type|
    if model.supported_action?(action_type, request)
      content << "<li class=\"#{'active' if type == action_type}\"><a href=\"#{url_for(action_type)}\">#{tab_name(action_type)}</a></li>"
    end
  end
  content << '</ul>'
end

#url_for(page) ⇒ Object

A path for the given page for the same model.



108
109
110
# File 'lib/autoforme/action.rb', line 108

def url_for(page)
  base_url_for("#{model.link}/#{page}")
end