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 +4 -4
- data/CHANGELOG +16 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +8 -10
- data/autoforme.js +97 -56
- data/lib/autoforme/action.rb +21 -21
- data/lib/autoforme/frameworks/rails.rb +5 -1
- data/lib/autoforme/frameworks/roda.rb +10 -4
- data/lib/autoforme/frameworks/sinatra.rb +8 -3
- data/lib/autoforme/models/sequel.rb +12 -2
- data/lib/autoforme/version.rb +1 -1
- data/lib/roda/plugins/autoforme.rb +1 -1
- metadata +6 -18
- data/Rakefile +0 -69
- data/spec/all.rb +0 -2
- data/spec/associations_spec.rb +0 -802
- data/spec/basic_spec.rb +0 -1168
- data/spec/mtm_spec.rb +0 -621
- data/spec/rails_spec_helper.rb +0 -108
- data/spec/roda_spec.rb +0 -72
- data/spec/roda_spec_helper.rb +0 -86
- data/spec/sequel_spec_helper.rb +0 -42
- data/spec/sinatra_spec_helper.rb +0 -54
- data/spec/spec_helper.rb +0 -78
- data/spec/unit_spec.rb +0 -511
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bff68076c7cdf213c0142df9ab3809d33ede301c99f12e5cfbe7d1e111df30d
|
4
|
+
data.tar.gz: d2446bc814e6a19ebb70dfd46717ac596bb0aa4915abf02dd83aded973ba8d65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
219
|
-
https://github.com/
|
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
|
-
|
2
|
-
var autoforme =
|
3
|
-
|
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(
|
6
|
-
|
7
|
-
|
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
|
-
|
13
|
-
var
|
14
|
-
var
|
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.
|
23
|
+
url += '?type=' + e.getAttribute('data-type');
|
21
24
|
if (exclude) {
|
22
25
|
url += '&exclude=' + exclude;
|
23
26
|
}
|
24
|
-
|
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.
|
31
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
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
|
-
|
119
|
+
e.preventDefault();
|
74
120
|
});
|
75
|
-
e.preventDefault();
|
76
121
|
});
|
77
|
-
};
|
78
|
-
|
79
|
-
|
80
|
-
$(document).ready(ready);
|
81
|
-
$(document).on('page:load', ready);
|
122
|
+
})();
|
data/lib/autoforme/action.rb
CHANGED
@@ -87,9 +87,7 @@ module AutoForme
|
|
87
87
|
else
|
88
88
|
return false unless model.supported_action?(normalized_type, request)
|
89
89
|
|
90
|
-
|
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)
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
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
|
-
|
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\/([
|
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[
|
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[
|
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
|
-
|
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
|
-
|
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.
|
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 =
|
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
|
data/lib/autoforme/version.rb
CHANGED
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.
|
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:
|
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.
|
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: []
|