reform 0.2.6 → 0.2.7

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: e0358800d71c3327b87d9d9659d789f67bd2195d
4
- data.tar.gz: bd6cba76f1f1b7a03b7a7d59599e7342b5bb9641
3
+ metadata.gz: e447e702b5effb25c8b881fb6c3056e57d39b5f9
4
+ data.tar.gz: 83ab3bdb3a48858fa273ea8985eb04bdee24e5d5
5
5
  SHA512:
6
- metadata.gz: 0df0530d354cca49618404e00466349af4c91b80021e7af1d69d2fb6302fd49a31727a4264d6628c3cb5c1f22b9f4c43a43e6da42ac1f2f8633659b14ff414c8
7
- data.tar.gz: 19c46cbabfbf81c5936417e209fdc4528f56a6847d9a541d542ca1fa00f7f0a5064653347dd759d6ffaab3a696d8037e40a007bdec332d97134f22339784f1d1
6
+ metadata.gz: 6891ad8debef392f1ac60f79c962bb42004325b15aa0d5ef460c1456ec03152c12dacf0e933193f2b0630042af1bc4a86ea9f564ab69e2f2d369cc3517a9dea0
7
+ data.tar.gz: 4a4014071fb1f71da66d6124ba79f007d1e09bd2854ba6f989e299e931c158a5500408c171eb7f714704b930246d3ff5df46cd00a9d87d00ec49ef501d4201c9
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.2.7
2
+
3
+ * Last release supporting Representable 1.7.
4
+ * In ActiveModel/ActiveRecord: The model name is now correctly infered even if the name is something like `Song::Form`.
5
+
1
6
  ## 0.2.6
2
7
 
3
8
  * Maintenance release cause I'm stupid.
@@ -6,6 +11,7 @@
6
11
 
7
12
  * Allow proper form inheritance. When having `HitForm < SongForm < Reform::Form` the `HitForm` class will contain `SongForm`'s properties in addition to its own fields.
8
13
  * `::model` is now inherited properly.
14
+ * Allow instantiation of nested form with emtpy nested properties.
9
15
 
10
16
  ## 0.2.4
11
17
 
data/README.md CHANGED
@@ -4,6 +4,10 @@ Decouple your models from forms. Reform gives you a form object with validations
4
4
 
5
5
  Although reform can be used in any Ruby framework, it comes with [Rails support](#rails-integration), works with [simple_form and other form gems](#formbuilder-support), allows nesting forms to implement [has_one](#nesting-forms-1-1-relations) and [has_many](#nesting-forms-1-n-relations) relationships, can [compose a form](#compositions) from multiple objects and gives you [coercion](#coercion).
6
6
 
7
+ # Development Status
8
+
9
+ Dear Reform users - you know I love all of you. Reform is currently being improved by myself. I am definitely *not* resisting all of the feature requests (especially about nesting, model validations, automatic model setup when validating has_many, etc.) but working hard to make it better. Expect a new Reform version _and_ better README mid-late April and please refrain from telling me how lazy I am. Thanks and see you soon!!! :heart:
10
+
7
11
 
8
12
  ## Installation
9
13
 
@@ -77,6 +81,10 @@ class SongsController
77
81
 
78
82
  Reform uses the validations you provided in the form - and nothing else.
79
83
 
84
+ Note that Reform only updates values of the internal form attributes - the underlying model is still treated as immutuable and *remains unchanged*.
85
+
86
+ This allows rendering the form after `validate` with the data that has been submitted. However, don't get confused, the model's values are still the old, original values and are only changed after a `#save` or `#sync` operation.
87
+
80
88
 
81
89
  ## Saving Forms
82
90
 
data/database.sqlite3 CHANGED
Binary file
data/lib/reform/form.rb CHANGED
@@ -76,6 +76,7 @@ module Reform
76
76
  res = valid? # this validates on <Fields> using AM::Validations, currently.
77
77
  #inject(true) do |res, form| # FIXME: replace that!
78
78
  mapper.new(@fields).nested_forms do |attr, form| #.collect { |attr, form| nested[attr.from] = form }
79
+ next unless form # FIXME: this happens when the model's reader returns nil (property :song => nil). this shouldn't be considered by nested_forms!
79
80
  res = validate_for(form, res, attr.from)
80
81
  end
81
82
 
@@ -119,6 +120,7 @@ module Reform
119
120
 
120
121
  def errors
121
122
  @errors ||= Errors.new(self)
123
+ @errors
122
124
  end
123
125
 
124
126
  attr_accessor :model
@@ -173,11 +175,14 @@ module Reform
173
175
 
174
176
  attr.options.merge!(
175
177
  :getter => lambda do |*|
176
- nested_model = send(attr.getter) # decorated.hit # TODO: use bin.get
178
+ # FIXME: this is where i have to fix stuff.
179
+ nested_model = send(attr.getter) # or next # decorated.hit # TODO: use bin.get # DISCUSS: next moves on if property empty. this should be handled with representable's built-in mechanics.
177
180
 
178
181
  if attr.options[:form_collection]
179
- Forms.new(nested_model.collect { |mdl| form_class.new(mdl)})
182
+ nested_model ||= []
183
+ Forms.new(nested_model.collect { |mdl| form_class.new(mdl)}, attr.options)
180
184
  else
185
+ next unless nested_model # DISCUSS: do we want that?
181
186
  form_class.new(nested_model)
182
187
  end
183
188
  end,
@@ -264,12 +269,16 @@ module Reform
264
269
  require "representable/hash/collection"
265
270
  require 'active_model'
266
271
  class Forms < Array # DISCUSS: this should be a Form subclass.
272
+ def initialize(ary, options)
273
+ super(ary)
274
+ @options = options
275
+ end
276
+
267
277
  include Form::ValidateMethods
268
278
 
279
+ # TODO: make valid?(errors) the only public method.
269
280
  def valid?
270
- inject(true) do |res, form|
271
- res = validate_for(form, res)
272
- end
281
+ res= validate_cardinality & validate_items
273
282
  end
274
283
 
275
284
  def errors
@@ -279,6 +288,22 @@ module Reform
279
288
  # this gives us each { to_hash }
280
289
  include Representable::Hash::Collection
281
290
  items :parse_strategy => :sync, :instance => true
291
+
292
+ private
293
+ def validate_items
294
+ inject(true) do |res, form|
295
+ res = validate_for(form, res)
296
+ end
297
+ end
298
+
299
+ def validate_cardinality
300
+ return true unless @options[:cardinality]
301
+ # TODO: use AM's cardinality validator here.
302
+ res = size >= @options[:cardinality][:minimum].to_i
303
+
304
+ errors.add(:size, "#{@options[:as]} size is 0 but must be #{@options[:cardinality].inspect}") unless res
305
+ res
306
+ end
282
307
  end
283
308
  end
284
309
 
@@ -78,7 +78,7 @@ module Reform::Form::ActiveModel
78
78
  if model_options
79
79
  form_name = model_options.first.to_s.camelize
80
80
  else
81
- form_name = name.sub(/Form$/, "")
81
+ form_name = name.sub(/(::)?Form$/, "") # Song::Form => "Song"
82
82
  end
83
83
 
84
84
  active_model_name_for(form_name)
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "0.2.6"
2
+ VERSION = "0.2.7"
3
3
  end
data/reform.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "representable", ">= 1.7.5"
21
+ spec.add_dependency "representable", "~> 1.7.5"
22
22
  spec.add_dependency "uber", "~> 0.0.4"
23
23
  spec.add_dependency "activemodel"
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -30,7 +30,7 @@ class NewActiveModelTest < MiniTest::Spec # TODO: move to test/rails/
30
30
 
31
31
  it { class_with_model.model_name.must_be_kind_of ActiveModel::Name }
32
32
  it { class_with_model.model_name.to_s.must_equal "Album" }
33
-
33
+
34
34
 
35
35
  let (:subclass_of_class_with_model) {
36
36
  Class.new(class_with_model)
@@ -40,6 +40,16 @@ class NewActiveModelTest < MiniTest::Spec # TODO: move to test/rails/
40
40
  it { subclass_of_class_with_model.model_name.to_s.must_equal 'Album' }
41
41
 
42
42
 
43
+ describe "class named Song::Form" do
44
+ it do
45
+ class Form < Reform::Form
46
+ include Reform::Form::ActiveModel
47
+ self
48
+ end.model_name.to_s.must_equal "NewActiveModelTest"
49
+ end
50
+ end
51
+
52
+
43
53
  describe "inline with model" do
44
54
  let (:form_class) {
45
55
  Class.new(Reform::Form) do
@@ -52,7 +62,7 @@ class NewActiveModelTest < MiniTest::Spec # TODO: move to test/rails/
52
62
  end
53
63
  }
54
64
 
55
- let (:inline) { form_class.new(OpenStruct.new).song }
65
+ let (:inline) { form_class.new(OpenStruct.new(:song => Object.new)).song }
56
66
 
57
67
  it { inline.class.model_name.must_be_kind_of ActiveModel::Name }
58
68
  it { inline.class.model_name.to_s.must_equal "Hit" }
@@ -41,11 +41,51 @@ class NestedFormTest < MiniTest::Spec
41
41
  form.to_hash.must_equal({"hit"=>{"title"=>"Downtown"}, "title" => "Blackhawks Over Los Angeles", "songs"=>[{"title"=>"Calling"}]})
42
42
  end
43
43
 
44
+
44
45
  it "creates nested forms" do
45
46
  form.hit.must_be_kind_of Reform::Form
46
47
  form.songs.must_be_kind_of Reform::Form::Forms
47
48
  end
48
49
 
50
+ describe "#initialize" do
51
+ describe "with empty object and no cardinality" do
52
+ let(:form) { AlbumForm.new(OpenStruct.new) }
53
+
54
+ it "allows initialization with empty properties" do
55
+ form
56
+ end
57
+
58
+ it "allows #validate" do
59
+ form.validate({})
60
+ form.errors.messages.must_equal(:title=>["can't be blank"])
61
+ end
62
+ # it "must support #validate when initialized with empty properties" do
63
+ # form.validate({})
64
+ # form.errors.messages.must_equal(:title=>["can't be blank"], :"hit.title"=>["can't be blank"], :"songs.title"=>["can't be blank"])
65
+ # end
66
+ # it "must support #validate with attributes when initialized with empty properties" do
67
+ # form.validate("hit"=>{"title"=>"Downtown"}, "title" => "Blackhawks Over Los Angeles", "songs"=>[{"title"=>"Calling"}])
68
+ # form.title.must_eql "Blackhawks Over Los Angeles"
69
+ # form.errors.messages.must_equal([])
70
+ # end
71
+ end
72
+
73
+ describe "with empty object and cardinality" do
74
+ subject { Class.new(Reform::Form) do
75
+ # collection :songs, :validates => {:length => {:minimum => 1}}
76
+ collection :songs, :cardinality => {:minimum => 1} do
77
+ property :title
78
+ end
79
+ end.new(OpenStruct.new) }
80
+
81
+ it "whatxxx" do
82
+ subject.validate({}).must_equal false
83
+ subject.errors.messages.must_equal(:"songs.size"=>["songs size is 0 but must be {:minimum=>1}"])
84
+ end
85
+ end
86
+ end
87
+
88
+
49
89
  describe "rendering" do
50
90
  it { form.title.must_equal "Blackhawks Over Los Angeles" }
51
91
  it { form.hit.title.must_equal "Downtown" }
@@ -171,4 +211,4 @@ class NestedFormTest < MiniTest::Spec
171
211
  end
172
212
  end
173
213
  end
174
- end
214
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
@@ -9,76 +9,76 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-15 00:00:00.000000000 Z
12
+ date: 2014-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: representable
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: 1.7.5
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - '>='
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: 1.7.5
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: uber
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ~>
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
34
  version: 0.0.4
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ~>
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: 0.0.4
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: activemodel
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '>='
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: bundler
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ~>
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '1.3'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ~>
67
+ - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '1.3'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rake
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - '>='
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: 10.1.0
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - '>='
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: 10.1.0
84
84
  - !ruby/object:Gem::Dependency
@@ -99,56 +99,56 @@ dependencies:
99
99
  name: activerecord
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - '>='
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - '>='
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: sqlite3
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - '>='
116
+ - - ">="
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - '>='
123
+ - - ">="
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: virtus
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  requirements:
130
- - - '>='
130
+ - - ">="
131
131
  - !ruby/object:Gem::Version
132
132
  version: '0'
133
133
  type: :development
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
- - - '>='
137
+ - - ">="
138
138
  - !ruby/object:Gem::Version
139
139
  version: '0'
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: rails
142
142
  requirement: !ruby/object:Gem::Requirement
143
143
  requirements:
144
- - - '>='
144
+ - - ">="
145
145
  - !ruby/object:Gem::Version
146
146
  version: '0'
147
147
  type: :development
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
- - - '>='
151
+ - - ">="
152
152
  - !ruby/object:Gem::Version
153
153
  version: '0'
154
154
  description: Freeing your AR models from form logic.
@@ -159,8 +159,8 @@ executables: []
159
159
  extensions: []
160
160
  extra_rdoc_files: []
161
161
  files:
162
- - .gitignore
163
- - .travis.yml
162
+ - ".gitignore"
163
+ - ".travis.yml"
164
164
  - CHANGES.md
165
165
  - Gemfile
166
166
  - LICENSE.txt
@@ -229,17 +229,17 @@ require_paths:
229
229
  - lib
230
230
  required_ruby_version: !ruby/object:Gem::Requirement
231
231
  requirements:
232
- - - '>='
232
+ - - ">="
233
233
  - !ruby/object:Gem::Version
234
234
  version: '0'
235
235
  required_rubygems_version: !ruby/object:Gem::Requirement
236
236
  requirements:
237
- - - '>='
237
+ - - ">="
238
238
  - !ruby/object:Gem::Version
239
239
  version: '0'
240
240
  requirements: []
241
241
  rubyforge_project:
242
- rubygems_version: 2.0.2
242
+ rubygems_version: 2.2.1
243
243
  signing_key:
244
244
  specification_version: 4
245
245
  summary: Decouples your models from form by giving you form objects with validation,