autoforme 1.0.3 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d88ff8420554c8c3bb3ae01e69dfaa2d5a10fd9
4
- data.tar.gz: 10dfb64d13724c261f2c88f7fa17747cb63ae134
3
+ metadata.gz: 728834eb84059f820d99421609b8f274868fa06f
4
+ data.tar.gz: 497582c00ccd77bcb14f716ae5596d32210ae33e
5
5
  SHA512:
6
- metadata.gz: d05a1e0e558f7a6c996f3d41b87daef5fc550cba51a351f5a207b7fb506511b92bd945e313867ce654d0b08b4d4b0f16755f1062a3444cd0a3dc2b05a2381064
7
- data.tar.gz: e43029905a7593fa791ea08483d6b73bce4428c5b09f6e3fa669edbc3716298f173ec9a95a5667106c9477b56321eeeb5f34010a686d7a59aa27d6baa64974db
6
+ metadata.gz: e71852cb6b1b049123b388d944789f8678b392724d299d776cd9ea43dd5ef3f6230d81135e11d6589a0610feb957e2838a1a3fd83181676f146089ec8832b837
7
+ data.tar.gz: ed0cecfc641fccdd7e1337421c3fdab68d38f4b1cbddbb470744924ffde7e9d35ab5e0c6b8205df8908bea8630a12ce392b9846fadb9f76166e0149495fe16cd
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.1.0 (2015-03-23)
2
+
3
+ * Add Framework#register_by_name to allow autoforme to work better when using code reloading in development (jeremyevans)
4
+
1
5
  === 1.0.3 (2015-01-27)
2
6
 
3
7
  * Fix homepage in gemspec (jeremyevans)
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Jeremy Evans
1
+ Copyright (c) 2013-2015 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
@@ -55,8 +55,8 @@ for Sinatra:
55
55
  end
56
56
 
57
57
  Let's break down how this works. You setup AutoForme using <tt>AutoForme.for</tt>,
58
- which takes 2 arguments, the controller type symbol (currently either :sinatra or :rails),
59
- and the controller class (either a Sinatra::Base or ActionController::Base subclass). You
58
+ which takes 2 arguments, the controller type symbol (currently either :sinatra, :roda, or :rails),
59
+ and the controller class (either a Sinatra::Base, Roda, or ActionController::Base subclass). You
60
60
  pass <tt>AutoForme.for</tt> a block, which is instance evaled at the framework level. This
61
61
  level sets the defaults.
62
62
 
@@ -212,6 +212,21 @@ AutoForme's javascript support is contained in the autoforme.js file in the root
212
212
  of the distribution. AutoForme's autocompleting support also requires
213
213
  https://github.com/dyve/jquery-autocomplete
214
214
 
215
+ = Reloading Code
216
+
217
+ By default, AutoForme stores classes by reference. This can cause issues when using
218
+ code reloading in development environments. You can call +register_by_name+ to set
219
+ Autoforme to store classes by name, so that if a class is removed and reloaded (giving
220
+ a new class reference), it will use the new class instead of the reference to the old
221
+ class. Example:
222
+
223
+ class App < Sinatra::Base
224
+ AutoForme.for(:sinatra, self) do
225
+ register_by_name
226
+ model Artist
227
+ end
228
+ end
229
+
215
230
  = TODO
216
231
 
217
232
  * capybara-webkit tests for ajax behavior
@@ -116,10 +116,30 @@ module AutoForme
116
116
  handle_proc(association_links, model, type, request)
117
117
  end
118
118
 
119
+ # Set whether to register classes by name instead of by reference
120
+ def register_by_name(register=true)
121
+ opts[:register_by_name] = register
122
+ end
123
+
124
+ # Whether to register classes by name instead of by reference
125
+ def register_by_name?
126
+ opts[:register_by_name]
127
+ end
128
+
129
+ # Look up the Autoforme::Model class to use for the underlying model class instance.
130
+ def model_class(model_class)
131
+ if register_by_name?
132
+ model_class = model_class.name
133
+ end
134
+ @model_classes[model_class]
135
+ end
136
+
119
137
  # Add a new model to the existing framework.
120
138
  def model(model_class, &block)
121
- model = Model.for(self, model_type, model_class, &block)
122
- @model_classes[model.model] = model
139
+ if register_by_name?
140
+ model_class = model_class.name
141
+ end
142
+ model = @model_classes[model_class] = Model.for(self, model_type, model_class, &block)
123
143
  @models[model.link] = model
124
144
  end
125
145
 
@@ -13,6 +13,9 @@ module AutoForme
13
13
  # The default supported actions for models.
14
14
  DEFAULT_SUPPORTED_ACTIONS = [:browse, :new, :show, :edit, :delete, :search, :mtm_edit]
15
15
 
16
+ # Regexp for valid constant names, to prevent code execution.
17
+ VALID_CONSTANT_NAME_REGEXP = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.freeze
18
+
16
19
  extend OptsAttributes
17
20
 
18
21
  # Create a new instance for the given model type and underlying model class
@@ -26,9 +29,6 @@ module AutoForme
26
29
  # The AutoForme::Framework class tied to the current model
27
30
  attr_reader :framework
28
31
 
29
- # The underlying model class for the current model
30
- attr_reader :model
31
-
32
32
  # The options for the given model.
33
33
  attr_reader :opts
34
34
 
@@ -47,6 +47,17 @@ module AutoForme
47
47
  @opts = {}
48
48
  end
49
49
 
50
+ # The underlying model class for the current model
51
+ def model
52
+ if @model.is_a?(Class)
53
+ @model
54
+ elsif m = VALID_CONSTANT_NAME_REGEXP.match(@model)
55
+ Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
56
+ else
57
+ raise Error, "invalid model for AutoForme::Model, not a class or valid constant name: #{@model.inspect}"
58
+ end
59
+ end
60
+
50
61
  # Whether the given type of action is supported for this model.
51
62
  def supported_action?(type, request)
52
63
  v = (handle_proc(supported_actions || framework.supported_actions_for(model, request), request) || DEFAULT_SUPPORTED_ACTIONS).include?(type)
@@ -223,7 +234,7 @@ module AutoForme
223
234
 
224
235
  # The AutoForme::Model instance associated to the given association.
225
236
  def associated_model_class(assoc)
226
- framework.model_classes[associated_class(assoc)]
237
+ framework.model_class(associated_class(assoc))
227
238
  end
228
239
 
229
240
  # The column value to display for the given object and column.
@@ -283,7 +294,7 @@ module AutoForme
283
294
  # Create a new instance of the underlying model, setting
284
295
  # defaults based on the params given.
285
296
  def new(params, request)
286
- obj = @model.new
297
+ obj = model.new
287
298
  if params
288
299
  columns_for(:new, request).each do |col|
289
300
  if association?(col)
@@ -11,7 +11,7 @@ module AutoForme
11
11
  # Make sure the forme plugin is loaded into the model.
12
12
  def initialize(*)
13
13
  super
14
- @model.plugin :forme
14
+ model.plugin :forme
15
15
  end
16
16
 
17
17
  # The base class for the underlying model, ::Sequel::Model.
@@ -21,7 +21,7 @@ module AutoForme
21
21
 
22
22
  # A completely empty search object, with no defaults.
23
23
  def new_search
24
- @model.call({})
24
+ model.call({})
25
25
  end
26
26
 
27
27
  # The name of the form param for the given association.
@@ -120,7 +120,7 @@ module AutoForme
120
120
  # The namespace for form parameter names for this model, needs to match
121
121
  # the ones automatically used by Forme.
122
122
  def params_name
123
- @model.send(:underscore, @model.name)
123
+ model.send(:underscore, model.name)
124
124
  end
125
125
 
126
126
  # Retrieve underlying model instance with matching primary key
@@ -329,7 +329,7 @@ module AutoForme
329
329
  private
330
330
 
331
331
  def dataset_for(type, request)
332
- ds = @model.dataset
332
+ ds = model.dataset
333
333
  if filter = filter_for
334
334
  ds = filter.call(ds, type, request)
335
335
  end
@@ -337,7 +337,7 @@ module AutoForme
337
337
  end
338
338
 
339
339
  def all_dataset_for(type, request)
340
- apply_dataset_options(type, request, @model.dataset)
340
+ apply_dataset_options(type, request, model.dataset)
341
341
  end
342
342
  end
343
343
  end
@@ -1,6 +1,6 @@
1
1
  module AutoForme
2
2
  # Version constant, use <tt>AutoForme.version</tt> instead.
3
- VERSION = '1.0.3'.freeze
3
+ VERSION = '1.1.0'.freeze
4
4
 
5
5
  # Returns the version as a frozen string (e.g. '0.1.0')
6
6
  def self.version
@@ -215,7 +215,7 @@ describe AutoForme do
215
215
  click_link 'Album'
216
216
  page.all('td').map{|s| s.text}.should == ["Album1b", "A2", "Show", "Edit", "Delete"]
217
217
 
218
- click_link 'Delete'
218
+ click_link 'Delete', :match=>:first
219
219
  select 'A2-Album1b'
220
220
  click_button 'Delete'
221
221
  end
@@ -293,7 +293,7 @@ describe AutoForme do
293
293
  click_link 'Album'
294
294
  page.all('tr td:first-child').map{|s| s.text}.should == %w'Y ZZ X'
295
295
 
296
- click_link 'Delete'
296
+ click_link 'Delete', :match=>:first
297
297
  page.all('select option').map{|s| s.text}.should == ['', 'A-Y', 'A-ZZ', 'B-X']
298
298
  select 'B-X'
299
299
  click_button 'Delete'
@@ -359,7 +359,7 @@ describe AutoForme do
359
359
  click_link 'Album'
360
360
  page.all('tr td:first-child').map{|s| s.text}.should == %w'C D E'
361
361
 
362
- click_link 'Delete'
362
+ click_link 'Delete', :match=>:first
363
363
  page.all('select option').map{|s| s.text}.should == ['', 'C', 'D', 'E']
364
364
  select 'C'
365
365
  click_button 'Delete'
@@ -410,7 +410,7 @@ describe AutoForme do
410
410
  click_link 'Artist'
411
411
  page.current_path.should == '/Artist/browse'
412
412
 
413
- click_link 'Edit'
413
+ click_link 'Edit', :match=>:first
414
414
  select 'Artist1'
415
415
  click_button 'Edit'
416
416
  click_link 'Album1'
@@ -490,7 +490,7 @@ describe AutoForme do
490
490
  click_link 'Artist'
491
491
  page.current_path.should == '/Artist/browse'
492
492
 
493
- click_link 'Edit'
493
+ click_link 'Edit', :match=>:first
494
494
  select 'Artist1'
495
495
  click_button 'Edit'
496
496
  click_link 'Show Associations'
@@ -12,20 +12,20 @@ describe AutoForme do
12
12
  it "should have basic functionality working" do
13
13
  app_setup(Artist)
14
14
  visit("/Artist/new")
15
- page.find('title').text.should == 'Artist - New'
15
+ page.title.should == 'Artist - New'
16
16
  fill_in 'Name', :with=>'TestArtistNew'
17
17
  click_button 'Create'
18
18
  page.html.should =~ /Created Artist/
19
19
  page.current_path.should == '/Artist/new'
20
20
 
21
21
  click_link 'Show'
22
- page.find('title').text.should == 'Artist - Show'
22
+ page.title.should == 'Artist - Show'
23
23
  select 'TestArtistNew'
24
24
  click_button 'Show'
25
25
  page.html.should =~ /Name.+TestArtistNew/m
26
26
 
27
27
  click_link 'Edit'
28
- page.find('title').text.should == 'Artist - Edit'
28
+ page.title.should == 'Artist - Edit'
29
29
  select 'TestArtistNew'
30
30
  click_button 'Edit'
31
31
  fill_in 'Name', :with=>'TestArtistUpdate'
@@ -35,7 +35,7 @@ describe AutoForme do
35
35
  page.current_path.should =~ %r{/Artist/edit/\d+}
36
36
 
37
37
  click_link 'Search'
38
- page.find('title').text.should == 'Artist - Search'
38
+ page.title.should == 'Artist - Search'
39
39
  fill_in 'Name', :with=>'Upd'
40
40
  click_button 'Search'
41
41
  page.all('th').map{|s| s.text}.should == ['Name', 'Show', 'Edit', 'Delete']
@@ -47,12 +47,12 @@ describe AutoForme do
47
47
  page.all('td').map{|s| s.text}.should == []
48
48
 
49
49
  click_link 'Artist'
50
- page.find('title').text.should == 'Artist - Browse'
50
+ page.title.should == 'Artist - Browse'
51
51
  page.all('td').map{|s| s.text}.should == ["TestArtistUpdate", "Show", "Edit", "Delete"]
52
52
 
53
53
  page.all('td').last.find('a').click
54
54
  click_button 'Delete'
55
- page.find('title').text.should == 'Artist - Delete'
55
+ page.title.should == 'Artist - Delete'
56
56
  page.html.should =~ /Deleted Artist/
57
57
  page.current_path.should == '/Artist/delete'
58
58
 
@@ -274,7 +274,7 @@ describe AutoForme do
274
274
  a.should == [:show, :browse]
275
275
  a.clear
276
276
 
277
- click_link 'Delete'
277
+ click_link 'Delete', :match=>:first
278
278
  Artist.create(:name=>'A')
279
279
  select 'WENTSITRATSET21'
280
280
  click_button 'Delete'
@@ -653,7 +653,7 @@ describe AutoForme do
653
653
  click_link 'Artist'
654
654
  page.all('tr td:first-child').map{|s| s.text}.should == %w'2 1'
655
655
 
656
- click_link 'Delete'
656
+ click_link 'Delete', :match=>:first
657
657
  page.all('option').map{|s| s.text}.should == ['', '2', '1']
658
658
  select '1'
659
659
  click_button 'Delete'
@@ -672,7 +672,7 @@ describe AutoForme do
672
672
  it "should display decimals in float format in tables" do
673
673
  app_setup(Artist)
674
674
  visit("/Artist/new")
675
- page.find('title').text.should == 'Artist - New'
675
+ page.title.should == 'Artist - New'
676
676
  fill_in 'Num', :with=>'1.01'
677
677
  click_button 'Create'
678
678
  click_link 'Artist'
@@ -682,3 +682,76 @@ describe AutoForme do
682
682
  page.all('tr td:first-child').map{|s| s.text}.should == %w'1.01'
683
683
  end
684
684
  end
685
+
686
+ describe AutoForme do
687
+ before(:all) do
688
+ db_setup(:artists=>[[:name, :string]])
689
+ model_setup(:Artist=>[:artists])
690
+ end
691
+ after(:all) do
692
+ Object.send(:remove_const, :Artist)
693
+ end
694
+
695
+ it "should have basic functionality working when reloading code" do
696
+ app_setup do
697
+ register_by_name
698
+ model Artist
699
+ end
700
+ artist_class = Artist
701
+ Object.send(:remove_const, :Artist)
702
+ ::Artist = Class.new(artist_class) do
703
+ def name
704
+ "-#{super}-"
705
+ end
706
+ def forme_name
707
+ "[#{name}]"
708
+ end
709
+ end
710
+ visit("/Artist/new")
711
+ page.title.should == 'Artist - New'
712
+ fill_in 'Name', :with=>'TestArtistNew'
713
+ click_button 'Create'
714
+ page.html.should =~ /Created Artist/
715
+ page.current_path.should == '/Artist/new'
716
+
717
+ click_link 'Show'
718
+ page.title.should == 'Artist - Show'
719
+ select '[-TestArtistNew-]'
720
+ click_button 'Show'
721
+ page.html.should =~ /Name.+-TestArtistNew-/m
722
+
723
+ click_link 'Edit'
724
+ page.title.should == 'Artist - Edit'
725
+ select '[-TestArtistNew-]'
726
+ click_button 'Edit'
727
+ fill_in 'Name', :with=>'TestArtistUpdate'
728
+ click_button 'Update'
729
+ page.html.should =~ /Updated Artist/
730
+ page.html.should =~ /Name.+-TestArtistUpdate-/m
731
+ page.current_path.should =~ %r{/Artist/edit/\d+}
732
+
733
+ click_link 'Search'
734
+ page.title.should == 'Artist - Search'
735
+ fill_in 'Name', :with=>'Upd'
736
+ click_button 'Search'
737
+ page.all('th').map{|s| s.text}.should == ['Name', 'Show', 'Edit', 'Delete']
738
+ page.all('td').map{|s| s.text}.should == ["-TestArtistUpdate-", "Show", "Edit", "Delete"]
739
+
740
+ click_link 'Search'
741
+ fill_in 'Name', :with=>'Foo'
742
+ click_button 'Search'
743
+ page.all('td').map{|s| s.text}.should == []
744
+
745
+ click_link 'Artist'
746
+ page.title.should == 'Artist - Browse'
747
+ page.all('td').map{|s| s.text}.should == ["-TestArtistUpdate-", "Show", "Edit", "Delete"]
748
+
749
+ page.all('td').last.find('a').click
750
+ click_button 'Delete'
751
+ page.html.should =~ /Deleted Artist/
752
+ page.current_path.should == '/Artist/delete'
753
+
754
+ click_link 'Artist'
755
+ page.all('td').map{|s| s.text}.should == []
756
+ end
757
+ end
@@ -36,7 +36,7 @@ describe AutoForme do
36
36
  Album.create(:name=>'Album3')
37
37
 
38
38
  visit("/Artist/mtm_edit")
39
- page.find('title').text.should == 'Artist - Many To Many Edit'
39
+ page.title.should == 'Artist - Many To Many Edit'
40
40
  select("Artist1")
41
41
  click_button "Edit"
42
42
 
@@ -123,7 +123,7 @@ describe AutoForme do
123
123
  click_button 'Add'
124
124
  Artist.first.refresh.albums.map{|x| x.name}.sort.should == %w'Album1 Album2'
125
125
 
126
- click_button 'Remove'
126
+ click_button 'Remove', :match=>:first
127
127
  Artist.first.refresh.albums.map{|x| x.name}.should == %w'Album2'
128
128
 
129
129
  select 'Album3'
@@ -158,7 +158,7 @@ describe AutoForme do
158
158
  click_button 'Add'
159
159
  Artist.first.refresh.albums.map{|x| x.name}.sort.should == %w'Album1 Album2'
160
160
 
161
- click_button 'Remove'
161
+ click_button 'Remove', :match=>:first
162
162
  Artist.first.refresh.albums.map{|x| x.name}.should == %w'Album2'
163
163
 
164
164
  fill_in 'Albums', :with=>a3.id.to_s
@@ -351,7 +351,7 @@ describe AutoForme do
351
351
  Album.create(:name=>'Album3')
352
352
 
353
353
  visit("/Artist/mtm_edit")
354
- page.find('title').text.should == 'Artist - Many To Many Edit'
354
+ page.title.should == 'Artist - Many To Many Edit'
355
355
  select("Artist1")
356
356
  click_button "Edit"
357
357
 
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.0.3
4
+ version: 1.1.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: 2015-01-27 00:00:00.000000000 Z
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forme