autoforme 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|