autoforme 1.9.1 → 1.10.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 +8 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +64 -4
- data/lib/autoforme/model.rb +1 -1
- data/lib/autoforme/models/sequel.rb +29 -6
- data/lib/autoforme/version.rb +2 -2
- data/spec/basic_spec.rb +12 -2
- data/spec/mtm_spec.rb +112 -0
- data/spec/rails_spec_helper.rb +32 -1
- data/spec/spec_helper.rb +1 -1
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f9fb399d144c4bfc7eed6e2a4f7497cab7bc25b8409d555c4f67fb91bad9bb7
|
4
|
+
data.tar.gz: bffb9114ef162400c639abb1ee17b7eb42ced481294d152e2603711c01752274
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15cd700c5edc91d860dcec0209dae57dd3db48ebe2bc6cf66f19b9d786d7a51b23f909ec80a0a2333af8d9c42c165690dd6710c26ebfadfbfa93c9d17618976b
|
7
|
+
data.tar.gz: 0c4a42c4e34e398209f98e85303558ef95447eb6a1e8f6351a182f214a1dab7b754f86aca8d81d35ba32d5890a09fa417a28c7e8212a2284df5d265c776533e8
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 1.10.0 (2021-08-27)
|
2
|
+
|
3
|
+
* Do not consider read_only many_to_many associations to be editable (jeremyevans)
|
4
|
+
|
5
|
+
* Ignore unique constraint violations when adding associated objects in mtm_update (jeremyevans)
|
6
|
+
|
7
|
+
* Handle search fields that cannot be typecast correctly by returning no results (jeremyevans)
|
8
|
+
|
1
9
|
=== 1.9.1 (2019-07-22)
|
2
10
|
|
3
11
|
* [SECURITY] Escape object display name when displaying association links (adam12)
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -22,8 +22,7 @@ flexible in terms of configuration.
|
|
22
22
|
Demo Site :: http://autoforme-demo.jeremyevans.net
|
23
23
|
RDoc :: http://autoforme.jeremyevans.net
|
24
24
|
Source :: https://github.com/jeremyevans/autoforme
|
25
|
-
|
26
|
-
Google Group :: https://groups.google.com/forum/#!forum/ruby-forme
|
25
|
+
Discussion Forum :: https://github.com/jeremyevans/autoforme/discussions
|
27
26
|
Bug Tracker :: https://github.com/jeremyevans/autoforme/issues
|
28
27
|
|
29
28
|
= Features
|
@@ -161,12 +160,13 @@ These options are related to displayed output:
|
|
161
160
|
|
162
161
|
form_attributes :: Hash of attributes to use for any form tags
|
163
162
|
form_options :: Hash of Forme::Form options to pass for any forms created
|
164
|
-
class_display_name :: The string to use when referring to the model class
|
163
|
+
class_display_name :: The string to use on pages when referring to the model class.
|
164
|
+
This defaults to the full class name.
|
165
165
|
display_name :: The string to use when referring to a model instance. Can either be a symbol
|
166
166
|
representing an instance method call, or a Proc called with the model object,
|
167
167
|
the model object and type symbol, or the model object, type symbol, and request,
|
168
168
|
depending on the arity of the Proc.
|
169
|
-
link_name :: The string to use in links for the class
|
169
|
+
link_name :: The string to use in links for the class. This defaults to +class_display_name+.
|
170
170
|
edit_html :: The html to use for a particular object edit field. Should be a proc that takes the
|
171
171
|
model object, column symbol, type symbol, and request and returns the html to use.
|
172
172
|
page_footer :: Override the default footer used for pages
|
@@ -238,6 +238,66 @@ use AutoForme in Rails development mode. The best way to handle it is to call
|
|
238
238
|
+AutoForme.for+ in the related controller file, and have an initializer reference
|
239
239
|
the controller class, causing the controller file to be loaded.
|
240
240
|
|
241
|
+
= Roda
|
242
|
+
|
243
|
+
Because Roda uses a routing tree, unlike Rails and Sinatra, with Roda you need to
|
244
|
+
dispatch to the autoforme routes at the point in the routing tree where you want
|
245
|
+
to mount them. Additionally, the Roda support offers a Roda plugin for easier
|
246
|
+
configuration.
|
247
|
+
|
248
|
+
To mount the autoforme routes in the root of the application, you could do:
|
249
|
+
|
250
|
+
class App < Roda
|
251
|
+
plugin :autoforme do
|
252
|
+
model Artist
|
253
|
+
end
|
254
|
+
|
255
|
+
route do
|
256
|
+
# rest of routing tree
|
257
|
+
autoforme
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
To mount the routes in a subpath:
|
262
|
+
|
263
|
+
class App < Roda
|
264
|
+
plugin :autoforme do
|
265
|
+
model Artist
|
266
|
+
end
|
267
|
+
|
268
|
+
route do
|
269
|
+
r.on "admin" do
|
270
|
+
autoforme
|
271
|
+
end
|
272
|
+
|
273
|
+
# rest of routing tree
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
To handle multiple autoforme configurations, mounted at different subpaths:
|
278
|
+
|
279
|
+
class App < Roda
|
280
|
+
plugin :autoforme
|
281
|
+
|
282
|
+
autoforme(name: 'artists')
|
283
|
+
model Artist
|
284
|
+
end
|
285
|
+
autoforme(name: 'albums')
|
286
|
+
model Album
|
287
|
+
end
|
288
|
+
|
289
|
+
route do
|
290
|
+
r.on "artists" do
|
291
|
+
autoforme('artists')
|
292
|
+
end
|
293
|
+
r.on "albums" do
|
294
|
+
autoforme('albums')
|
295
|
+
end
|
296
|
+
|
297
|
+
# rest of routing tree
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
241
301
|
= TODO
|
242
302
|
|
243
303
|
* capybara-webkit tests for ajax behavior
|
data/lib/autoforme/model.rb
CHANGED
@@ -98,14 +98,26 @@ module AutoForme
|
|
98
98
|
ref[:keys].zip(ref[:primary_keys].map{|k| obj.send(k)})
|
99
99
|
end
|
100
100
|
|
101
|
+
# Array of many to many association name strings for editable
|
102
|
+
# many to many associations.
|
103
|
+
def editable_mtm_association_names
|
104
|
+
association_names([:many_to_many]) do |r|
|
105
|
+
model.method_defined?(r.add_method) && model.method_defined?(r.remove_method)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
101
109
|
# Array of many to many association name strings.
|
102
110
|
def mtm_association_names
|
103
111
|
association_names([:many_to_many])
|
104
112
|
end
|
105
113
|
|
106
|
-
# Array of association name strings for given association types
|
114
|
+
# Array of association name strings for given association types. If a block is
|
115
|
+
# given, only include associations where the block returns truthy.
|
107
116
|
def association_names(types=SUPPORTED_ASSOCIATION_TYPES)
|
108
|
-
model.all_association_reflections.
|
117
|
+
model.all_association_reflections.
|
118
|
+
select{|r| types.include?(r[:type]) && (!block_given? || yield(r))}.
|
119
|
+
map{|r| r[:name]}.
|
120
|
+
sort_by(&:to_s)
|
109
121
|
end
|
110
122
|
|
111
123
|
# Save the object, returning the object if successful, or nil if not.
|
@@ -158,7 +170,7 @@ module AutoForme
|
|
158
170
|
params = request.params
|
159
171
|
ds = apply_associated_eager(:search, request, all_dataset_for(type, request))
|
160
172
|
columns_for(:search_form, request).each do |c|
|
161
|
-
if (v = params[c.to_s]) && !v.empty?
|
173
|
+
if (v = params[c.to_s]) && !(v = v.to_s).empty?
|
162
174
|
if association?(c)
|
163
175
|
ref = model.association_reflection(c)
|
164
176
|
ads = ref.associated_dataset
|
@@ -168,9 +180,16 @@ module AutoForme
|
|
168
180
|
primary_key = S.qualify(ref.associated_class.table_name, ref.primary_key)
|
169
181
|
ds = ds.where(S.qualify(model.table_name, ref[:key])=>ads.where(primary_key=>v).select(primary_key))
|
170
182
|
elsif column_type(c) == :string
|
171
|
-
ds = ds.where(S.ilike(S.qualify(model.table_name, c), "%#{ds.escape_like(v
|
183
|
+
ds = ds.where(S.ilike(S.qualify(model.table_name, c), "%#{ds.escape_like(v)}%"))
|
172
184
|
else
|
173
|
-
|
185
|
+
begin
|
186
|
+
typecasted_value = model.db.typecast_value(column_type(c), v)
|
187
|
+
rescue S::InvalidValue
|
188
|
+
ds = ds.where(false)
|
189
|
+
break
|
190
|
+
else
|
191
|
+
ds = ds.where(S.qualify(model.table_name, c)=>typecasted_value)
|
192
|
+
end
|
174
193
|
end
|
175
194
|
end
|
176
195
|
end
|
@@ -293,7 +312,11 @@ module AutoForme
|
|
293
312
|
ids.each do |id|
|
294
313
|
next if id.to_s.empty?
|
295
314
|
ret = assoc_class ? assoc_class.with_pk(:association, request, id) : obj.send(:_apply_association_options, ref, ref.associated_class.dataset.clone).with_pk!(id)
|
296
|
-
|
315
|
+
begin
|
316
|
+
model.db.transaction(:savepoint=>true){obj.send(meth, ret)}
|
317
|
+
rescue S::UniqueConstraintViolation
|
318
|
+
# Already added, safe to ignore
|
319
|
+
end
|
297
320
|
end
|
298
321
|
end
|
299
322
|
end
|
data/lib/autoforme/version.rb
CHANGED
@@ -6,11 +6,11 @@ module AutoForme
|
|
6
6
|
MAJOR = 1
|
7
7
|
|
8
8
|
# The minor version of AutoForme, updated for new feature releases of AutoForme.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 10
|
10
10
|
|
11
11
|
# The patch version of AutoForme, updated only for bug fixes from the last
|
12
12
|
# feature release.
|
13
|
-
TINY =
|
13
|
+
TINY = 0
|
14
14
|
|
15
15
|
# Version constant, use <tt>AutoForme.version</tt> instead.
|
16
16
|
VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze
|
data/spec/basic_spec.rb
CHANGED
@@ -954,19 +954,29 @@ describe AutoForme do
|
|
954
954
|
after(:all) do
|
955
955
|
Object.send(:remove_const, :Artist)
|
956
956
|
end
|
957
|
-
|
958
|
-
it "should display decimals in float format in tables" do
|
957
|
+
before do
|
959
958
|
app_setup(Artist)
|
960
959
|
visit("/Artist/new")
|
961
960
|
page.title.must_equal 'Artist - New'
|
962
961
|
fill_in 'Num', :with=>'1.01'
|
963
962
|
click_button 'Create'
|
963
|
+
visit("/Artist/browse")
|
964
|
+
end
|
965
|
+
|
966
|
+
it "should display decimals in float format in tables" do
|
964
967
|
click_link 'Artist'
|
965
968
|
page.all('tr td:first-child').map{|s| s.text}.must_equal %w'1.01'
|
966
969
|
click_link 'Search'
|
967
970
|
click_button 'Search'
|
968
971
|
page.all('tr td:first-child').map{|s| s.text}.must_equal %w'1.01'
|
969
972
|
end
|
973
|
+
|
974
|
+
it "should treat invalid search fields as returning no results" do
|
975
|
+
click_link 'Search'
|
976
|
+
fill_in 'Num', :with=>'3/3/2020'
|
977
|
+
click_button 'Search'
|
978
|
+
page.all('tr td:first-child').map{|s| s.text}.must_equal []
|
979
|
+
end
|
970
980
|
end
|
971
981
|
|
972
982
|
describe AutoForme do
|
data/spec/mtm_spec.rb
CHANGED
@@ -507,3 +507,115 @@ describe AutoForme do
|
|
507
507
|
page.all('select')[1].all('option').map{|s| s.text}.must_equal ["Album2", "Album3"]
|
508
508
|
end
|
509
509
|
end
|
510
|
+
|
511
|
+
describe AutoForme do
|
512
|
+
before(:all) do
|
513
|
+
db_setup(:artists=>[[:name, :string]], :albums=>[[:name, :string]], :albums_artists=>proc{column :album_id, :integer, :table=>:albums; column :artist_id, :integer, :table=>:artists; primary_key [:album_id, :artist_id]})
|
514
|
+
model_setup(:Artist=>[:artists, [[:many_to_many, :albums]]], :Album=>[:albums, [[:many_to_many, :artists]]])
|
515
|
+
end
|
516
|
+
after(:all) do
|
517
|
+
Object.send(:remove_const, :Album)
|
518
|
+
Object.send(:remove_const, :Artist)
|
519
|
+
end
|
520
|
+
|
521
|
+
it "should handle unique constraint violation errors when adding associated objects" do
|
522
|
+
app_setup do
|
523
|
+
model Artist do
|
524
|
+
mtm_associations :albums
|
525
|
+
end
|
526
|
+
model Album
|
527
|
+
end
|
528
|
+
|
529
|
+
artist = Artist.create(:name=>'Artist1')
|
530
|
+
album = Album.create(:name=>'Album1')
|
531
|
+
|
532
|
+
visit("/Artist/mtm_edit")
|
533
|
+
page.title.must_equal 'Artist - Many To Many Edit'
|
534
|
+
select("Artist1")
|
535
|
+
click_button "Edit"
|
536
|
+
|
537
|
+
find('h2').text.must_equal 'Edit Albums for Artist1'
|
538
|
+
page.all('select')[0].all('option').map{|s| s.text}.must_equal ["Album1"]
|
539
|
+
page.all('select')[1].all('option').map{|s| s.text}.must_equal []
|
540
|
+
select("Album1", :from=>"Associate With")
|
541
|
+
artist.add_album(album)
|
542
|
+
click_button "Update"
|
543
|
+
page.html.must_include 'Updated albums association for Artist'
|
544
|
+
Artist.first.albums.map{|x| x.name}.must_equal %w'Album1'
|
545
|
+
end
|
546
|
+
|
547
|
+
it "should handle unique constraint violation errors when adding associated objects" do
|
548
|
+
app_setup do
|
549
|
+
model Artist do
|
550
|
+
mtm_associations :albums
|
551
|
+
end
|
552
|
+
model Album
|
553
|
+
end
|
554
|
+
|
555
|
+
artist = Artist.create(:name=>'Artist1')
|
556
|
+
album = Album.create(:name=>'Album1')
|
557
|
+
artist.add_album(album)
|
558
|
+
|
559
|
+
visit("/Artist/mtm_edit")
|
560
|
+
page.title.must_equal 'Artist - Many To Many Edit'
|
561
|
+
select("Artist1")
|
562
|
+
click_button "Edit"
|
563
|
+
|
564
|
+
find('h2').text.must_equal 'Edit Albums for Artist1'
|
565
|
+
page.all('select')[0].all('option').map{|s| s.text}.must_equal []
|
566
|
+
page.all('select')[1].all('option').map{|s| s.text}.must_equal ["Album1"]
|
567
|
+
select("Album1", :from=>"Disassociate From")
|
568
|
+
artist.remove_album(album)
|
569
|
+
click_button "Update"
|
570
|
+
page.html.must_include 'Updated albums association for Artist'
|
571
|
+
Artist.first.albums.map{|x| x.name}.must_equal []
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
describe AutoForme do
|
576
|
+
before(:all) do
|
577
|
+
db_setup(:artists=>[[:name, :string]], :albums=>[[:name, :string]], :albums_artists=>[[:album_id, :integer, {:table=>:albums}], [:artist_id, :integer, {:table=>:artists}]])
|
578
|
+
model_setup(:Artist=>[:artists, [[:many_to_many, :albums, :read_only=>true]]], :Album=>[:albums, [[:many_to_many, :artists, :read_only=>true]]])
|
579
|
+
end
|
580
|
+
after(:all) do
|
581
|
+
Object.send(:remove_const, :Album)
|
582
|
+
Object.send(:remove_const, :Artist)
|
583
|
+
end
|
584
|
+
|
585
|
+
it "should not automatically setup mtm support for read-only associations" do
|
586
|
+
app_setup do
|
587
|
+
model Artist do
|
588
|
+
mtm_associations :all
|
589
|
+
association_links :all
|
590
|
+
end
|
591
|
+
model Album do
|
592
|
+
mtm_associations :all
|
593
|
+
association_links :all
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
visit("/Artist/new")
|
598
|
+
page.html.wont_include 'MTM'
|
599
|
+
fill_in 'Name', :with=>'Artist1'
|
600
|
+
click_button 'Create'
|
601
|
+
click_link 'Edit'
|
602
|
+
select 'Artist1'
|
603
|
+
click_button 'Edit'
|
604
|
+
page.html.must_include 'Albums'
|
605
|
+
page.html.wont_include '>associate<'
|
606
|
+
visit("/Artist/mtm_edit")
|
607
|
+
page.html.must_include 'Unhandled Request'
|
608
|
+
|
609
|
+
visit("/Album/new")
|
610
|
+
page.html.wont_include 'MTM'
|
611
|
+
fill_in 'Name', :with=>'Album1'
|
612
|
+
click_button 'Create'
|
613
|
+
click_link 'Edit'
|
614
|
+
select 'Album1'
|
615
|
+
click_button 'Edit'
|
616
|
+
page.html.must_include 'Artists'
|
617
|
+
page.html.wont_include '>associate<'
|
618
|
+
visit("/Album/mtm_edit")
|
619
|
+
page.html.must_include 'Unhandled Request'
|
620
|
+
end
|
621
|
+
end
|
data/spec/rails_spec_helper.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rails'
|
2
3
|
require 'action_controller/railtie'
|
3
4
|
require 'autoforme'
|
4
5
|
|
5
6
|
class AutoFormeSpec::App
|
7
|
+
class << self
|
8
|
+
# Workaround for action_view railtie deleting the finalizer
|
9
|
+
attr_accessor :av_finalizer
|
10
|
+
end
|
11
|
+
|
6
12
|
def self.autoforme(klass=nil, opts={}, &block)
|
7
13
|
sc = Class.new(Rails::Application)
|
8
14
|
def sc.name
|
@@ -16,7 +22,7 @@ class AutoFormeSpec::App
|
|
16
22
|
resolver = Class.new(ActionView::Resolver)
|
17
23
|
resolver.class_eval do
|
18
24
|
template = ActionView::Template
|
19
|
-
|
25
|
+
code = (<<HTML)
|
20
26
|
<!DOCTYPE html>
|
21
27
|
<html>
|
22
28
|
<head><title><%= @autoforme_action.title if @autoforme_action %></title></head>
|
@@ -30,6 +36,11 @@ class AutoFormeSpec::App
|
|
30
36
|
<%= yield %>
|
31
37
|
</body></html>"
|
32
38
|
HTML
|
39
|
+
if Rails.version > '6'
|
40
|
+
t = [template.new(code, "layout", template.handler_for_extension(:erb), :virtual_path=>'layout', :format=>'erb', :locals=>[])]
|
41
|
+
else
|
42
|
+
t = [template.new(code, "layout", template.handler_for_extension(:erb), :virtual_path=>'layout', :format=>'erb', :updated_at=>Time.now)]
|
43
|
+
end
|
33
44
|
|
34
45
|
define_method(:find_templates){|*args| t}
|
35
46
|
end
|
@@ -57,11 +68,23 @@ HTML
|
|
57
68
|
get 'session/set', :controller=>'autoforme', :action=>'session_set'
|
58
69
|
end.inspect
|
59
70
|
config.secret_token = st if Rails.respond_to?(:version) && Rails.version < '5.2'
|
71
|
+
config.hosts << "www.example.com" if config.respond_to?(:hosts)
|
60
72
|
config.active_support.deprecation = :stderr
|
61
73
|
config.middleware.delete(ActionDispatch::ShowExceptions)
|
62
74
|
config.middleware.delete(Rack::Lock)
|
63
75
|
config.secret_key_base = st*15
|
64
76
|
config.eager_load = true
|
77
|
+
if Rails.version.start_with?('4')
|
78
|
+
# Work around issue in backported openssl environments where
|
79
|
+
# secret is 64 bytes intead of 32 bytes
|
80
|
+
require 'active_support/message_encryptor'
|
81
|
+
ActiveSupport::MessageEncryptor.send :prepend, Module.new {
|
82
|
+
def initialize(secret, *signature_key_or_options)
|
83
|
+
secret = secret[0, 32]
|
84
|
+
super
|
85
|
+
end
|
86
|
+
}
|
87
|
+
end
|
65
88
|
if Rails.version > '4.2'
|
66
89
|
config.action_dispatch.cookies_serializer = :json
|
67
90
|
end
|
@@ -70,6 +93,14 @@ HTML
|
|
70
93
|
ActionDispatch::Routing::RouteSet::Dispatcher.class_eval do
|
71
94
|
define_method(:controller){|_| controller}
|
72
95
|
end
|
96
|
+
config.session_store :cookie_store, :key=>'_autoforme_test_session'
|
97
|
+
end
|
98
|
+
if Rails.version > '6'
|
99
|
+
if AutoFormeSpec::App.av_finalizer
|
100
|
+
config.action_view.finalize_compiled_template_methods = AutoFormeSpec::App.av_finalizer
|
101
|
+
else
|
102
|
+
AutoFormeSpec::App.av_finalizer = config.action_view.finalize_compiled_template_methods
|
103
|
+
end
|
73
104
|
end
|
74
105
|
initialize!
|
75
106
|
end
|
data/spec/spec_helper.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.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: forme
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 1.1.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest-global_expectations
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: capybara
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -243,7 +257,12 @@ files:
|
|
243
257
|
homepage: http://github.com/jeremyevans/autoforme
|
244
258
|
licenses:
|
245
259
|
- MIT
|
246
|
-
metadata:
|
260
|
+
metadata:
|
261
|
+
bug_tracker_uri: https://github.com/jeremyevans/autoforme/issues
|
262
|
+
changelog_uri: http://autoforme.jeremyevans.net/files/CHANGELOG.html
|
263
|
+
documentation_uri: http://autoforme.jeremyevans.net
|
264
|
+
mailing_list_uri: https://github.com/jeremyevans/autoforme/discussions
|
265
|
+
source_code_uri: https://github.com/jeremyevans/autoforme
|
247
266
|
post_install_message:
|
248
267
|
rdoc_options:
|
249
268
|
- "--quiet"
|
@@ -266,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
285
|
- !ruby/object:Gem::Version
|
267
286
|
version: '0'
|
268
287
|
requirements: []
|
269
|
-
rubygems_version: 3.
|
288
|
+
rubygems_version: 3.2.22
|
270
289
|
signing_key:
|
271
290
|
specification_version: 4
|
272
291
|
summary: Web Administrative Console for Roda/Sinatra/Rails and Sequel::Model
|