reform 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 201a01642c1743227a0209c716240374d884189f
4
- data.tar.gz: 4327aa39fbfae302b0078c6787a0df387aa08080
3
+ metadata.gz: 76401e86f77b8b06874c24e8257dc97e5d0e66c0
4
+ data.tar.gz: 37e55343b9fc0d9b7d7764c4988f01f22db0d4fc
5
5
  SHA512:
6
- metadata.gz: 42bad26c32be288977aae6cc6be0f634382b5bdc0cc733ce5b0f2084096db897df33b7126923b58f9d3eee4f50e63b1ee0095650a2c414c12a2c1e9fbc5148fd
7
- data.tar.gz: 94ebe84171e96c49fff4adbdc704d5c94cebc0713a27a35b86941ffc33e23947e7371afe9b8d6fce3f7bffee1cd6ba2363418635abd87f65230bbebf7b2bf385
6
+ metadata.gz: 9b7b1d9f9ed49bff28ac3bd83802b8d73d20005bd9126a1d25b6a342e031a0e44a5ed675686242468c29c2ac7bf7c5b71bb7bf40c53ec5811d26ba601c02ca97
7
+ data.tar.gz: 557e270fa0dfbaad214790f3aaa0bf579d90feeb4b70a5193fcd2bb526b4ada902d3308081ae67b0a6fdcd13b2048afd389b9625cf7c9a8819668a3c1f247095
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.2.5
2
+
3
+ * Allow proper form inheritance. When having `HitForm < SongForm < Reform::Form` the `HitForm` class will contain `SongForm`'s properties in addition to its own fields.
4
+ * `::model` is now inherited properly.
5
+
1
6
  ## 0.2.4
2
7
 
3
8
  * Accessors for properties (e.g. `title` and `title=`) can now be overridden in the form *and* call `super`. This is extremely helpful if you wanna do "manual coercion" since the accessors are invoked in `#validate`. Thanks to @cj for requesting this.
data/README.md CHANGED
@@ -271,12 +271,17 @@ class SongWithLabelForm < Reform::Form
271
271
  property :title, on: :song
272
272
  property :city, on: :label
273
273
 
274
+ model :song # only needed in ActiveModel context.
275
+
274
276
  validates :title, :city, presence: true
275
277
  end
276
278
  ```
277
279
 
278
280
  Note that reform needs to know about the owner objects of properties. You can do so by using the `on:` option.
279
281
 
282
+ Also, the form needs to have a main object configured. This is where ActiveModel-methods like `#persisted?` or '#id' are delegated to. Use `::model` to define the main object.
283
+
284
+
280
285
  ### Composition: Setup
281
286
 
282
287
  The constructor slightly differs.
@@ -415,6 +420,15 @@ Reform provides the following `ActiveRecord` specific features. They're mixed in
415
420
  * Uniqueness validations. Use `validates_uniqueness_of` in your form.
416
421
  * Calling `Form#save` will explicitely call `save` on your model (added in 0.2.1) which will usually trigger a database insertion or update.
417
422
 
423
+ As mentioned in the [Rails Integration](https://github.com/apotonick/reform#rails-integration) section some Rails 4 setups do not properly load.
424
+
425
+ You may want to include the module manually then.
426
+
427
+ ```ruby
428
+ class SongForm < Reform::Form
429
+ include Reform::Form::ActiveRecord
430
+ ```
431
+
418
432
 
419
433
  ## ActiveModel Compliance
420
434
 
Binary file
@@ -4,15 +4,18 @@ require 'ostruct'
4
4
  require 'reform/composition'
5
5
  require 'reform/representer'
6
6
 
7
+ require 'uber/inheritable_attr'
8
+
9
+
7
10
  module Reform
8
11
  class Form
9
12
  extend Forwardable
10
- # reasons for delegation:
11
- # presentation: this object is used in the presentation layer by #form_for.
12
- # problem: #form_for uses respond_to?(:email_before_type_cast) which goes to an internal hash in the actual record.
13
- # validation: this object also contains the validation rules itself, should be separated.
14
13
 
15
- # Allows using property and friends in the Form itself. Forwarded to the internal representer_class.
14
+ extend Uber::InheritableAttr
15
+ inheritable_attr :representer_class
16
+ self.representer_class = Class.new(Reform::Representer)
17
+
18
+
16
19
  module PropertyMethods
17
20
  extend Forwardable
18
21
 
@@ -43,10 +46,6 @@ module Reform
43
46
  definition.options[:instance] = true # just to make typed? work
44
47
  end
45
48
 
46
- def representer_class
47
- @representer_class ||= Class.new(Reform::Representer)
48
- end
49
-
50
49
  private
51
50
  def create_accessor(name)
52
51
  # Make a module that contains these very accessors, then include it
@@ -55,18 +55,28 @@ module Reform::Form::ActiveModel
55
55
  end
56
56
  end
57
57
 
58
+
58
59
  module ClassMethods
60
+ # this module is only meant to extend (not include). # DISCUSS: is this a sustainable concept?
61
+ def self.extended(base)
62
+ base.class_eval do
63
+ extend Hooks::InheritableAttribute
64
+ inheritable_attr :model_options
65
+ end
66
+ end
67
+
68
+
59
69
  # Set a model name for this form if the infered is wrong.
60
70
  #
61
71
  # class CoverSongForm < Reform::Form
62
72
  # model :song
63
73
  def model(main_model, options={})
64
- @model_options = [main_model, options] # FIXME: make inheritable!
74
+ self.model_options = [main_model, options]
65
75
  end
66
76
 
67
77
  def model_name
68
- if @model_options
69
- form_name = @model_options.first.to_s.camelize
78
+ if model_options
79
+ form_name = model_options.first.to_s.camelize
70
80
  else
71
81
  form_name = name.sub(/Form$/, "")
72
82
  end
@@ -5,12 +5,13 @@ class Reform::Form
5
5
  module Composition
6
6
  def self.included(base)
7
7
  base.class_eval do
8
+ extend Reform::Form::ActiveModel::ClassMethods # ::model.
8
9
  extend ClassMethods
9
10
  end
10
11
  end
11
12
 
12
13
  module ClassMethods
13
- include Reform::Form::ActiveModel::ClassMethods # ::model.
14
+ #include Reform::Form::ActiveModel::ClassMethods # ::model.
14
15
 
15
16
  def model_class # DISCUSS: needed?
16
17
  rpr = representer_class
@@ -47,6 +47,10 @@ module Reform
47
47
  each(&block)
48
48
  end
49
49
 
50
+ def self.clone # called in inheritable_attr :representer_class.
51
+ Class.new(self) # By subclassing, representable_attrs.clone is called.
52
+ end
53
+
50
54
  private
51
55
  def clone_config!
52
56
  # TODO: representable_attrs.clone! which does exactly what's done below.
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -19,10 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "representable", ">= 1.7.5"
22
+ spec.add_dependency "uber", "~> 0.0.4"
22
23
  spec.add_dependency "activemodel"
23
24
  spec.add_development_dependency "bundler", "~> 1.3"
24
25
  spec.add_development_dependency "rake", ">= 10.1.0"
25
- spec.add_development_dependency "minitest"
26
+ spec.add_development_dependency "minitest", "4.2.0"
26
27
  spec.add_development_dependency "activerecord"
27
28
  spec.add_development_dependency "sqlite3"
28
29
  spec.add_development_dependency "virtus"
@@ -30,6 +30,15 @@ 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
+
34
+
35
+ let (:subclass_of_class_with_model) {
36
+ Class.new(class_with_model)
37
+ }
38
+
39
+ it { subclass_of_class_with_model.model_name.must_be_kind_of ActiveModel::Name }
40
+ it { subclass_of_class_with_model.model_name.to_s.must_equal 'Album' }
41
+
33
42
 
34
43
  describe "inline with model" do
35
44
  let (:form_class) {
@@ -198,6 +207,18 @@ class ActiveModelWithCompositionTest < MiniTest::Spec
198
207
  model :song
199
208
  end.new(:song => rio, :artist => duran).song.must_equal rio
200
209
  end
210
+
211
+ # it "delegates when you call ::model" do
212
+ # class SongOnlyForm < Reform::Form
213
+ # include Composition
214
+ # include Reform::Form::ActiveModel
215
+
216
+ # property :title, :on => :song
217
+ # model :song
218
+
219
+ # self
220
+ # end.new(:song => rio, :artist => duran).persisted?
221
+ # end
201
222
  end
202
223
 
203
224
 
@@ -240,4 +261,4 @@ class ActiveModelWithCompositionTest < MiniTest::Spec
240
261
 
241
262
  AnotherForm.new(:song => rio).song.must_equal rio
242
263
  end
243
- end
264
+ end
@@ -112,12 +112,14 @@ class ReformTest < ReformSpec
112
112
  end
113
113
 
114
114
  it "exposes input via property accessors" do
115
- comp.name.must_equal nil
116
- form.name.must_equal nil
117
-
118
115
  form.validate("name" => "Duran Duran")
119
116
 
120
117
  form.name.must_equal "Duran Duran"
118
+ end
119
+
120
+ it "doesn't change model properties" do
121
+ form.validate("name" => "Duran Duran")
122
+
121
123
  comp.name.must_equal nil # don't touch model, yet.
122
124
  end
123
125
 
@@ -213,6 +215,22 @@ class ReformTest < ReformSpec
213
215
  describe "#model" do
214
216
  it { form.model.must_equal comp }
215
217
  end
218
+
219
+
220
+ describe "inheritance" do
221
+ class HitForm < SongForm
222
+ property :position
223
+ validates :position, :presence => true
224
+ end
225
+
226
+ let (:form) { HitForm.new(OpenStruct.new) }
227
+ it do
228
+ form.validate({"title" => "The Body"})
229
+ form.title.must_equal "The Body"
230
+ form.position.must_equal nil
231
+ form.errors.messages.must_equal({:name=>["can't be blank"], :position=>["can't be blank"]})
232
+ end
233
+ end
216
234
  end
217
235
 
218
236
  class EmptyAttributesTest < MiniTest::Spec
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.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-22 00:00:00.000000000 Z
12
+ date: 2014-03-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: representable
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: 1.7.5
28
+ - !ruby/object:Gem::Dependency
29
+ name: uber
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 0.0.4
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 0.0.4
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: activemodel
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -71,16 +85,16 @@ dependencies:
71
85
  name: minitest
72
86
  requirement: !ruby/object:Gem::Requirement
73
87
  requirements:
74
- - - '>='
88
+ - - '='
75
89
  - !ruby/object:Gem::Version
76
- version: '0'
90
+ version: 4.2.0
77
91
  type: :development
78
92
  prerelease: false
79
93
  version_requirements: !ruby/object:Gem::Requirement
80
94
  requirements:
81
- - - '>='
95
+ - - '='
82
96
  - !ruby/object:Gem::Version
83
- version: '0'
97
+ version: 4.2.0
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: activerecord
86
100
  requirement: !ruby/object:Gem::Requirement
@@ -225,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
239
  version: '0'
226
240
  requirements: []
227
241
  rubyforge_project:
228
- rubygems_version: 2.0.3
242
+ rubygems_version: 2.0.2
229
243
  signing_key:
230
244
  specification_version: 4
231
245
  summary: Decouples your models from form by giving you form objects with validation,