autoforme 1.11.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0198a23636933034920c066694a4acd8e58d5529fbf21ada5f542a7de444cc2c'
4
- data.tar.gz: 6cf1f310f06018a91573472c7410c1dda1842b7f96593a82deaf9be5f2bdd524
3
+ metadata.gz: 2bff68076c7cdf213c0142df9ab3809d33ede301c99f12e5cfbe7d1e111df30d
4
+ data.tar.gz: d2446bc814e6a19ebb70dfd46717ac596bb0aa4915abf02dd83aded973ba8d65
5
5
  SHA512:
6
- metadata.gz: 8931ddb513d806df30b8a4fe36fb20583597ac4e9f45e1144c5732cff66d09f92a14967a5ac4c35724ac339bfd23af866b454490ffabe99b327dfaff2e1aa787
7
- data.tar.gz: '097239f8074dc20537dec29064f24c2e5fbb521cf3586bb828726afc2b436eed190794d2b276e9b108c60bb6a4c3116a35dc651d54e32af5ff74d34e4a6b586e'
6
+ metadata.gz: '048c064a080ae50bd872be8e17a96f06e6f9eece5fb095c31121810edbe2f03d1f5db7a6562fb0d33c7229b1e1a49641246186f6567435664be646da836ce251'
7
+ data.tar.gz: 596b1caa6bfc6a91cf8745019df9c299e9315ace558388c9c5ba4fb44b7df18fdfd0aff0c9e5a7213c71e26ffb3fa12d3afed34e91c962e1ae258254413cded4
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ === 1.13.0 (2024-07-10)
2
+
3
+ * Typecast primary key values before using them for lookup (jeremyevans)
4
+
5
+ * Support colon for model names to allow easier use of namespaced models (adam12) (#46)
6
+
7
+ === 1.12.0 (2022-06-29)
8
+
9
+ * Handle autocomplete queries with an empty query by returning empty string (jeremyevans)
10
+
11
+ * Switch autocomplete support to depend on Pixabay/JavaScript-autoComplete (jeremyevans)
12
+
13
+ * Make autoforme.js file no longer require JQuery (jeremyevans)
14
+
15
+ * Make navigation tab li tag use nav-item, for Bootstrap 5 compatibility (jeremyevans)
16
+
1
17
  === 1.11.0 (2021-11-30)
2
18
 
3
19
  * Require forme 2.0.0 (jeremyevans)
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2021 Jeremy Evans
1
+ Copyright (c) 2013-2024 Jeremy Evans
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/README.rdoc CHANGED
@@ -6,12 +6,7 @@ integrate easily into web frameworks, and currently supports
6
6
  Roda, Sinatra, and Rails. The only currently supported ORM is
7
7
  Sequel::Model.
8
8
 
9
- AutoForme's UI and capabilities are modeled on
10
- scaffolding_extensions [2], though AutoForme is considerably more
11
- flexible in terms of configuration.
12
-
13
9
  1. https://github.com/jeremyevans/forme
14
- 2. https://github.com/jeremyevans/scaffolding_extensions
15
10
 
16
11
  = Installation
17
12
 
@@ -214,9 +209,12 @@ AutoForme also has javascript support for the progressive enhancement of the fol
214
209
  * Loading association links via ajax if lazy_load_association_links is true.
215
210
  * Adding and removing many-to-many associated objects via ajax for inline_mtm_associations
216
211
 
217
- AutoForme's javascript support is contained in the autoforme.js file in the root
218
- of the distribution. AutoForme's autocompleting support also requires
219
- https://github.com/dyve/jquery-autocomplete
212
+ AutoForme's javascript support is contained in the +autoforme.js+ file in the root
213
+ of the repository. AutoForme's autocompleting support also requires
214
+ https://github.com/Pixabay/JavaScript-autoComplete
215
+
216
+ Make sure to load the +autoforme.js+ file after the DOM content has been loaded, such
217
+ as at the end of the body.
220
218
 
221
219
  = Reloading Code
222
220
 
@@ -281,10 +279,10 @@ To handle multiple autoforme configurations, mounted at different subpaths:
281
279
  class App < Roda
282
280
  plugin :autoforme
283
281
 
284
- autoforme(name: 'artists')
282
+ autoforme(name: 'artists') do
285
283
  model Artist
286
284
  end
287
- autoforme(name: 'albums')
285
+ autoforme(name: 'albums') do
288
286
  model Album
289
287
  end
290
288
 
data/autoforme.js CHANGED
@@ -1,81 +1,122 @@
1
- var ready = function() {
2
- var autoforme = $('#autoforme_content');
3
- var base_url = autoforme.data('url');
1
+ (function() {
2
+ var autoforme = document.querySelector('#autoforme_content');
3
+ if (!autoforme) {
4
+ return;
5
+ }
6
+ var base_url = autoforme.getAttribute('data-url');
7
+ var xhr_headers = {'X-Requested-With': 'XMLHttpRequest'};
4
8
 
5
- function autoforme_fix_autocomplete(e) {
6
- $(e).find('.autoforme_autocomplete').each(function(){
7
- $(this).val($(this).val().split(' - ', 2)[0]);
9
+ function autoforme_fix_autocomplete(form) {
10
+ form.querySelectorAll('.autoforme_autocomplete').forEach((e) => {
11
+ e.value = e.value.split(' - ', 2)[0];
8
12
  });
9
13
  }
10
14
 
11
- function autoforme_setup_autocomplete() {
12
- autoforme.find('.autoforme_autocomplete').each(function(){
13
- var e = $(this);
14
- var column = e.data('column');
15
- var exclude = e.data('exclude');
15
+ function autoforme_setup_autocomplete(content) {
16
+ content.querySelectorAll('.autoforme_autocomplete').forEach((e) => {
17
+ var column = e.getAttribute('data-column');
18
+ var exclude = e.getAttribute('data-exclude');
16
19
  var url = base_url + 'autocomplete';
17
20
  if (column) {
18
21
  url += '/' + column;
19
22
  }
20
- url += '?type=' + e.data('type');
23
+ url += '?type=' + e.getAttribute('data-type');
21
24
  if (exclude) {
22
25
  url += '&exclude=' + exclude;
23
26
  }
24
- e.autocomplete(url);
27
+
28
+ new autoComplete({
29
+ selector: '[id="'+e.getAttribute("id")+'"]',
30
+ source: function(term, suggest) {
31
+ fetch((url + '&q=' + term), {headers: xhr_headers}).
32
+ then(function(response) {
33
+ return response.text();
34
+ }).
35
+ then(function(body) {
36
+ suggest(body.split("\n"));
37
+ });
38
+ }
39
+ });
25
40
  });
26
41
  }
27
42
 
28
- autoforme_setup_autocomplete();
43
+ autoforme_setup_autocomplete(autoforme);
29
44
 
30
- autoforme.on('submit', 'form', function(e){
31
- autoforme_fix_autocomplete(this);
45
+ autoforme.querySelectorAll("form").forEach((form) => {
46
+ form.addEventListener('submit', function(){
47
+ autoforme_fix_autocomplete(form);
48
+ }, {passive: true});
32
49
  });
33
50
 
51
+ var lazy_load_association_links = autoforme.querySelector('#lazy_load_association_links');
52
+ if (lazy_load_association_links) {
53
+ load_association_links = function(e) {
54
+ e.preventDefault();
55
+ lazy_load_association_links.removeEventListener('click', load_association_links);
34
56
 
35
- $('#lazy_load_association_links').click(function(e){
36
- var t = $(this);
37
- t.load(base_url + "association_links/" + t.data('object') + "?type=" + t.data('type'), autoforme_setup_autocomplete);
38
- t.unbind('click');
39
- e.preventDefault();
40
- });
57
+ var url = base_url + "association_links/" + load_association_links.getAttribute('data-object') + "?type=" + load_association_links.getAttribute('data-type');
58
+ fetch(url, {headers: xhr_headers}).
59
+ then(function(response) {
60
+ return response.text();
61
+ }).
62
+ then(function(body) {
63
+ lazy_load_association_links.innerHTML = body;
64
+ autoforme_setup_autocomplete(lazy_load_association_links);
65
+ });
66
+ };
67
+ lazy_load_association_links.addEventListener('click', load_association_links);
68
+ }
41
69
 
42
- autoforme.on('submit', '.mtm_add_associations', function(e){
43
- var form = $(this);
44
- if (form.find('.autoforme_autocomplete').length == 0) {
45
- var select = form.find('select')[0];
46
- $.post(this.action, form.serialize(), function(data, textStatus){
47
- $(select).find('option:selected').remove();
48
- select.selectedIndex = 0;
49
- $(form.data('remove')).append(data);
50
- });
51
- } else {
52
- autoforme_fix_autocomplete(form);
53
- $.post(this.action, form.serialize(), function(data, textStatus){
54
- var t = form.find('.autoforme_autocomplete');
55
- t.val('');
56
- t.data('autocompleter').cacheFlush();
57
- $(form.data('remove')).append(data);
70
+ setup_remove_hooks = function() {
71
+ autoforme.querySelectorAll('.inline_mtm_remove_associations form.mtm_remove_associations').forEach((form) => {
72
+ if (form.remove_hook_setup) {return;}
73
+ form.remove_hook_setup = true;
74
+
75
+ form.addEventListener('submit', function(e){
76
+ fetch(form.action, {method: 'post', body: new FormData(form), headers: xhr_headers}).
77
+ then(function(response) {
78
+ return response.text();
79
+ }).
80
+ then(function(body) {
81
+ document.querySelector(form.getAttribute('data-add')).insertAdjacentHTML('beforeend', body);
82
+ form.parentElement.remove();
83
+ });
84
+ e.preventDefault();
58
85
  });
59
- }
60
- e.preventDefault();
61
- });
86
+ });
87
+ };
88
+ setup_remove_hooks();
89
+
90
+ autoforme.querySelectorAll('.mtm_add_associations').forEach((form) => {
91
+ form.addEventListener('submit', function(e){
92
+ var form_ac = form.querySelector('.autoforme_autocomplete');
93
+ if (!form_ac) {
94
+ var select = form.querySelector('select');
62
95
 
63
- autoforme.on('submit', '.inline_mtm_remove_associations form', function(e){
64
- var form = $(this);
65
- var parent = form.parent();
66
- $.post(this.action, form.serialize(), function(data, textStatus){
67
- var t = $(form.data('add'));
68
- if (t[0].type == "text") {
69
- t.data('autocompleter').cacheFlush();
96
+ fetch(form.action, {method: 'post', body: new FormData(form), headers: xhr_headers}).
97
+ then(function(response) {
98
+ return response.text();
99
+ }).
100
+ then(function(body) {
101
+ select.remove(select.selectedIndex);
102
+ select.selectedIndex = 0;
103
+ document.querySelector(form.getAttribute('data-remove')).insertAdjacentHTML('beforeend', body);
104
+ setup_remove_hooks();
105
+ });
70
106
  } else {
71
- t.append(data);
107
+ autoforme_fix_autocomplete(form);
108
+
109
+ fetch(form.action, {method: 'post', body: new FormData(form), headers: xhr_headers}).
110
+ then(function(response) {
111
+ return response.text();
112
+ }).
113
+ then(function(body) {
114
+ form_ac.value = '';
115
+ document.querySelector(form.getAttribute('data-remove')).insertAdjacentHTML('beforeend', body);
116
+ setup_remove_hooks();
117
+ });
72
118
  }
73
- parent.remove();
119
+ e.preventDefault();
74
120
  });
75
- e.preventDefault();
76
121
  });
77
- };
78
-
79
-
80
- $(document).ready(ready);
81
- $(document).on('page:load', ready);
122
+ })();
@@ -87,9 +87,7 @@ module AutoForme
87
87
  else
88
88
  return false unless model.supported_action?(normalized_type, request)
89
89
 
90
- if title = TITLE_MAP[@normalized_type]
91
- @title = "#{model.class_name} - #{title}"
92
- end
90
+ @title = "#{model.class_name} - #{TITLE_MAP[@normalized_type]}"
93
91
  end
94
92
 
95
93
  true
@@ -134,7 +132,7 @@ module AutoForme
134
132
  type.to_s
135
133
  when :edit
136
134
  "edit/#{model.primary_key_value(obj)}"
137
- when :mtm_edit
135
+ else # when :mtm_edit
138
136
  "mtm_edit/#{model.primary_key_value(obj)}?association=#{params_association}"
139
137
  end
140
138
  path = url_for(path)
@@ -195,7 +193,7 @@ module AutoForme
195
193
  content << '<ul class="nav nav-tabs">'
196
194
  Model::DEFAULT_SUPPORTED_ACTIONS.each do |action_type|
197
195
  if model.supported_action?(action_type, request)
198
- content << "<li class=\"#{'active' if type == action_type}\"><a href=\"#{url_for(action_type)}\">#{tab_name(action_type)}</a></li>"
196
+ content << "<li class=\"nav-item #{'active' if type == action_type}\"><a class=\"nav-link\" href=\"#{url_for(action_type)}\">#{tab_name(action_type)}</a></li>"
199
197
  end
200
198
  end
201
199
  content << '</ul>'
@@ -315,19 +313,19 @@ module AutoForme
315
313
  if html = model.show_html_for(obj, column, type, request)
316
314
  col_opts = col_opts.merge(:html=>html)
317
315
  end
318
- t << f.input(column, col_opts).to_s
316
+ t << f.input(column, col_opts)
319
317
  end
320
318
  t << '</table>'
321
319
  if type == :show && model.supported_action?(:edit, request)
322
320
  t << Forme.form(form_attributes(:action=>url_for("edit/#{model.primary_key_value(obj)}")), form_opts) do |f1|
323
321
  f1.button(:value=>'Edit', :class=>'btn btn-primary')
324
- end.to_s
322
+ end
325
323
  end
326
324
  if type == :delete
327
325
  form_attr = form_attributes(:action=>url_for("destroy/#{model.primary_key_value(obj)}"), :method=>:post)
328
326
  t << Forme.form(form_attr, form_opts(form_attr[:action])) do |f1|
329
327
  f1.button(:value=>'Delete', :class=>'btn btn-danger')
330
- end.to_s
328
+ end
331
329
  else
332
330
  t << association_links(obj)
333
331
  end
@@ -358,11 +356,11 @@ module AutoForme
358
356
  f.input(column, col_opts)
359
357
  end
360
358
  f.button(:value=>'Update', :class=>'btn btn-primary')
361
- end.to_s
359
+ end
362
360
  if model.supported_action?(:delete, request)
363
361
  t << Forme.form(form_attributes(:action=>url_for("delete/#{model.primary_key_value(obj)}")), form_opts) do |f|
364
362
  f.button(:value=>'Delete', :class=>'btn btn-danger')
365
- end.to_s
363
+ end
366
364
  end
367
365
  t << association_links(obj)
368
366
  end
@@ -492,15 +490,15 @@ module AutoForme
492
490
  opts = model.column_options_for(:mtm_edit, request, assoc)
493
491
  add_opts = opts[:add] ? opts.merge(opts.delete(:add)) : opts
494
492
  remove_opts = opts[:remove] ? opts.merge(opts.delete(:remove)) : opts
495
- add_opts = {:name=>'add[]', :id=>'add', :label=>'Associate With'}.merge(add_opts)
493
+ add_opts = {:name=>'add[]', :id=>'add', :label=>'Associate With'}.merge!(add_opts)
496
494
  if model.association_autocomplete?(assoc, request)
497
- 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))
495
+ 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))
498
496
  else
499
- f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj), :size=>10}.merge(add_opts))
497
+ f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj), :size=>10}.merge!(add_opts))
500
498
  end
501
- f.input(assoc, {:name=>'remove[]', :id=>'remove', :label=>'Disassociate From', :dataset=>model.associated_mtm_objects(request, assoc, obj), :value=>[], :size=>10}.merge(remove_opts))
499
+ f.input(assoc, {:name=>'remove[]', :id=>'remove', :label=>'Disassociate From', :dataset=>model.associated_mtm_objects(request, assoc, obj), :value=>[], :size=>10}.merge!(remove_opts))
502
500
  f.button(:value=>'Update', :class=>'btn btn-primary')
503
- end.to_s
501
+ end
504
502
  end
505
503
  else
506
504
  page do
@@ -545,7 +543,9 @@ module AutoForme
545
543
 
546
544
  # Handle autocomplete action by returning a string with one line per model object.
547
545
  def handle_autocomplete
548
- unless (query = request.params['q'].to_s).empty?
546
+ if (query = request.params['q'].to_s).empty?
547
+ ''
548
+ else
549
549
  model.autocomplete(:type=>@subtype, :request=>request, :association=>params_association, :query=>query, :exclude=>request.params['exclude']).join("\n")
550
550
  end
551
551
  end
@@ -653,14 +653,14 @@ module AutoForme
653
653
  t << Forme.form(obj, form_attr, form_opts(form_attr[:action])) do |f|
654
654
  opts = model.column_options_for(:mtm_edit, request, assoc)
655
655
  add_opts = opts[:add] ? opts.merge(opts.delete(:add)) : opts.dup
656
- add_opts = {:name=>'add[]', :id=>"add_#{assoc}"}.merge(add_opts)
656
+ add_opts = {:name=>'add[]', :id=>"add_#{assoc}"}.merge!(add_opts)
657
657
  if model.association_autocomplete?(assoc, request)
658
- 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))
658
+ 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))
659
659
  else
660
- f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj), :multiple=>false, :add_blank=>true}.merge(add_opts))
660
+ f.input(assoc, {:dataset=>model.unassociated_mtm_objects(request, assoc, obj), :multiple=>false, :add_blank=>true}.merge!(add_opts))
661
661
  end
662
662
  f.button(:value=>'Add', :class=>'btn btn-xs btn-primary')
663
- end.to_s
663
+ end
664
664
  end
665
665
  t << "</div>"
666
666
  t << "<div class='inline_mtm_remove_associations'><ul>"
@@ -685,7 +685,7 @@ module AutoForme
685
685
  form_attr = form_attributes(:action=>url_for("mtm_update/#{model.primary_key_value(obj)}?association=#{assoc}&remove%5b%5d=#{model.primary_key_value(assoc_obj)}&redir=edit"), :method=>'post', :class => 'mtm_remove_associations', 'data-add'=>"#add_#{assoc}")
686
686
  t << Forme.form(form_attr, form_opts(form_attr[:action])) do |f|
687
687
  f.button(:value=>'Remove', :class=>'btn btn-xs btn-danger')
688
- end.to_s
688
+ end
689
689
  t << "</li>"
690
690
  end
691
691
  end
@@ -31,7 +31,11 @@ module AutoForme
31
31
  # Use Rails's form_authenticity_token for CSRF protection.
32
32
  def csrf_token_hash(action=nil)
33
33
  vc = @controller.view_context
34
- {vc.request_forgery_protection_token.to_s=>vc.form_authenticity_token} if vc.protect_against_forgery?
34
+ # :nocov:
35
+ if vc.protect_against_forgery?
36
+ # :nocov:
37
+ {vc.request_forgery_protection_token.to_s=>vc.form_authenticity_token}
38
+ end
35
39
  end
36
40
  end
37
41
 
@@ -23,7 +23,7 @@ module AutoForme
23
23
  # :nocov:
24
24
  end
25
25
 
26
- path_id = $1 if remaining_path =~ %r{\A\/([\w-]+)\z}
26
+ path_id = $1 if remaining_path =~ %r{\A\/([:\w-]+)\z}
27
27
  set_id(path_id)
28
28
  end
29
29
 
@@ -40,13 +40,13 @@ module AutoForme
40
40
  # Set the flash at notice level when redirecting, so it shows
41
41
  # up on the redirected page.
42
42
  def set_flash_notice(message)
43
- @controller.flash[flash_symbol_keys? ? :notice : 'notice'] = message
43
+ @controller.flash[flash_key(:notice)] = message
44
44
  end
45
45
 
46
46
  # Set the current flash at error level, used when displaying
47
47
  # pages when there is an error.
48
48
  def set_flash_now_error(message)
49
- @controller.flash.now[flash_symbol_keys? ? :error : 'error'] = message
49
+ @controller.flash.now[flash_key(:error)] = message
50
50
  end
51
51
 
52
52
  # Use Rack::Csrf for csrf protection if it is defined.
@@ -62,7 +62,7 @@ module AutoForme
62
62
  end
63
63
  {@controller.csrf_field=>token}
64
64
  # :nocov:
65
- elsif defined?(::Rack::Csrf)
65
+ elsif defined?(::Rack::Csrf) && !@controller.opts[:no_csrf]
66
66
  {::Rack::Csrf.field=>::Rack::Csrf.token(@env)}
67
67
  # :nocov:
68
68
  end
@@ -73,6 +73,12 @@ module AutoForme
73
73
  def flash_symbol_keys?
74
74
  !@controller.opts[:sessions_convert_symbols]
75
75
  end
76
+
77
+ def flash_key(key)
78
+ # :nocov:
79
+ flash_symbol_keys? ? key : key.to_s
80
+ # :nocov:
81
+ end
76
82
  end
77
83
 
78
84
  attr_reader :route_proc
@@ -30,7 +30,11 @@ module AutoForme
30
30
 
31
31
  # Use Rack::Csrf for csrf protection if it is defined.
32
32
  def csrf_token_hash(action=nil)
33
- {::Rack::Csrf.field=>::Rack::Csrf.token(@env)} if defined?(::Rack::Csrf)
33
+ # :nocov:
34
+ if defined?(::Rack::Csrf)
35
+ # :nocov:
36
+ {::Rack::Csrf.field=>::Rack::Csrf.token(@env)}
37
+ end
34
38
  end
35
39
  end
36
40
 
@@ -51,7 +55,6 @@ module AutoForme
51
55
  @autoforme_text
52
56
  else
53
57
  opts = framework.opts[:view_options]
54
- opts = opts ? opts.dup : {}
55
58
  erb("<%= @autoforme_text %>".dup, opts ? opts.dup : {})
56
59
  end
57
60
  else
@@ -60,11 +63,13 @@ module AutoForme
60
63
  end
61
64
 
62
65
  prefix = Regexp.escape(framework.prefix) if framework.prefix
66
+ # :nocov:
63
67
  if ::Sinatra::VERSION < '2'
64
68
  prefix = "\\A#{prefix}"
65
69
  suffix = "\\z"
66
70
  end
67
- regexp = %r{#{prefix}/([\w:]+)/(\w+)(?:/([\w-]+))?#{suffix}}
71
+ # :nocov:
72
+ regexp = %r{#{prefix}/([\w:]+)/(\w+)(?:/([:\w-]+))?#{suffix}}
68
73
  @controller.get regexp, &block
69
74
  @controller.post regexp, &block
70
75
  end
@@ -133,6 +133,12 @@ module AutoForme
133
133
 
134
134
  # Retrieve underlying model instance with matching primary key
135
135
  def with_pk(type, request, pk)
136
+ begin
137
+ pk = typecast_value(model.primary_key, pk)
138
+ rescue S::InvalidValue
139
+ raise S::NoMatchingRow
140
+ end
141
+
136
142
  dataset_for(type, request).with_pk!(pk)
137
143
  end
138
144
 
@@ -150,7 +156,7 @@ module AutoForme
150
156
  columns[i] = reflection[:name]
151
157
  end
152
158
  end
153
- columns.sort_by(&:to_s)
159
+ columns.sort!
154
160
  end
155
161
 
156
162
  # Add a filter restricting access to only rows where the column name
@@ -183,7 +189,7 @@ module AutoForme
183
189
  ds = ds.where(S.ilike(S.qualify(model.table_name, c), "%#{ds.escape_like(v)}%"))
184
190
  else
185
191
  begin
186
- typecasted_value = model.db.typecast_value(column_type(c), v)
192
+ typecasted_value = typecast_value(c, v)
187
193
  rescue S::InvalidValue
188
194
  ds = ds.where(false)
189
195
  break
@@ -355,6 +361,10 @@ module AutoForme
355
361
 
356
362
  private
357
363
 
364
+ def typecast_value(column, value)
365
+ model.db.typecast_value(column_type(column), value)
366
+ end
367
+
358
368
  def dataset_for(type, request)
359
369
  ds = model.dataset
360
370
  if filter = filter_for
@@ -6,7 +6,7 @@ module AutoForme
6
6
  MAJOR = 1
7
7
 
8
8
  # The minor version of AutoForme, updated for new feature releases of AutoForme.
9
- MINOR = 11
9
+ MINOR = 13
10
10
 
11
11
  # The patch version of AutoForme, updated only for bug fixes from the last
12
12
  # feature release.
@@ -6,7 +6,7 @@ class Roda
6
6
  module RodaPlugins
7
7
  module AutoForme
8
8
  # Require the render plugin, since it is required.
9
- def self.load_dependencies(app, opts={})
9
+ def self.load_dependencies(app, opts={}, &_)
10
10
  app.plugin :render
11
11
  end
12
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autoforme
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-30 00:00:00.000000000 Z
11
+ date: 2024-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forme
@@ -228,7 +228,6 @@ files:
228
228
  - CHANGELOG
229
229
  - MIT-LICENSE
230
230
  - README.rdoc
231
- - Rakefile
232
231
  - autoforme.js
233
232
  - lib/autoforme.rb
234
233
  - lib/autoforme/action.rb
@@ -243,17 +242,6 @@ files:
243
242
  - lib/autoforme/table.rb
244
243
  - lib/autoforme/version.rb
245
244
  - lib/roda/plugins/autoforme.rb
246
- - spec/all.rb
247
- - spec/associations_spec.rb
248
- - spec/basic_spec.rb
249
- - spec/mtm_spec.rb
250
- - spec/rails_spec_helper.rb
251
- - spec/roda_spec.rb
252
- - spec/roda_spec_helper.rb
253
- - spec/sequel_spec_helper.rb
254
- - spec/sinatra_spec_helper.rb
255
- - spec/spec_helper.rb
256
- - spec/unit_spec.rb
257
245
  homepage: http://github.com/jeremyevans/autoforme
258
246
  licenses:
259
247
  - MIT
@@ -263,7 +251,7 @@ metadata:
263
251
  documentation_uri: http://autoforme.jeremyevans.net
264
252
  mailing_list_uri: https://github.com/jeremyevans/autoforme/discussions
265
253
  source_code_uri: https://github.com/jeremyevans/autoforme
266
- post_install_message:
254
+ post_install_message:
267
255
  rdoc_options:
268
256
  - "--quiet"
269
257
  - "--line-numbers"
@@ -285,8 +273,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
273
  - !ruby/object:Gem::Version
286
274
  version: '0'
287
275
  requirements: []
288
- rubygems_version: 3.2.32
289
- signing_key:
276
+ rubygems_version: 3.5.11
277
+ signing_key:
290
278
  specification_version: 4
291
279
  summary: Web Administrative Console for Roda/Sinatra/Rails and Sequel::Model
292
280
  test_files: []