reform 2.0.0.rc3 → 2.0.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: 1656561190a1c9784f1e2463e6c4e2c558bb78d0
4
- data.tar.gz: 236cc4811f68a6e6e6e7a9e0a31d11a4afbe955d
3
+ metadata.gz: 247ffc53838f5e69a71f4ab5d066572b05308003
4
+ data.tar.gz: f6162c6a018e02ad2f9c487441dcea08623b960a
5
5
  SHA512:
6
- metadata.gz: 2aa18198338829e843a002d940dfb60d0f4d318662637d064f01a668f30fd59bf20fa3fe11dd25b7a5534e93b986aabc54d19cf2f01e3e42f02c81273fe7601a
7
- data.tar.gz: 4d9cea3a1c22769400c48164b2a907e0b8f713a82b2cb9e11fb0fb97bbc963f3a5445da828b4b899b2dd4b420416fb7b7d94f1f6c400378e47210c64028d99f5
6
+ metadata.gz: 31ee6b2d4656b94ced0c7790832e8b6be84ea2b8218866c5cb9e75c6b3099710e9e2a52a24cd54b9c40ba0ead9a9712e7e961ac4b463f48bb34131b305c22246
7
+ data.tar.gz: d8954f5806cdbbd701b4e8352d930f2b1bd3aef5a36d5621ef154a0132e6e46481137b5f1d9208932a0377805f81cac75ee066885cf73b2ea4778957e8c1192b
data/CHANGES.md CHANGED
@@ -2,18 +2,25 @@
2
2
 
3
3
  * The `::reform_2_0!` is no longer there. Guess why.
4
4
  * Again: `:empty` doesn't exist anymore. You can choose from `:readable`, `:writeable` and `:virtual`.
5
- * :populator => lambda { |fragment, index, args|
6
- # songs[index] or songs[index] = args.binding[:form].new(Song.new)
7
- # }
8
- is now :populator => lambda { |fragment, index, args|
9
- # songs[index] or songs.insert(index) = Song.new
10
- # }
11
- you don't need to know about forms anymore, the twin handles that using #insert.
5
+ * When using `:populator` the API to work against the form has changed.
6
+ ```ruby
7
+ populator: lambda { |fragment, index, args|
8
+ songs[index] or songs[index] = args.binding[:form].new(Song.new)
9
+ }
10
+ ```
11
+
12
+ is now
13
+
14
+ ```ruby
15
+ populator: lambda { |fragment, index, args|
16
+ songs[index] or songs.insert(index) = Song.new
17
+ }
18
+ ```
19
+ You don't need to know about forms anymore, the twin handles that using the [Twin](https://github.com/apotonick/disposable) API..
12
20
 
13
21
  * `:as` option removed. Use `:from`.
14
22
  * With `Composition` included, `Form#model` would give you a composition object. You can grab that using `Form#mapper` now.
15
23
  * `Form#update!` is deprecated. It still works but will remind you to override `#present!` or use pre-populators as [described here](http://trailblazerb.org/gems/reform/prepopulator.html) and in the Trailblazer book, chapter "Nested Forms".
16
-
17
24
  * Forms do not `include ActiveModel::Validations` anymore. This has polluted the entire gem and is not encapsulated in `Validator`. Consider using Lotus Validations instead.
18
25
  * Validation inheritance with `ActiveModel::Validations` is broken with Rails 3.2 and 4.0. Update Rails or use the `Lotus` validations.
19
26
 
data/README.md CHANGED
@@ -123,7 +123,7 @@ Sometimes, you need to do saving manually.
123
123
 
124
124
  ## Saving Forms Manually
125
125
 
126
- Calling `#save` with a block doesn't do anything but provide you with a nested hash with all the validated input. This allows you to implement the saving yourself.
126
+ Calling `#save` with a block will provide a nested hash of the form's properties and values. This does **not call `#save` on the models** and allows you to implement the saving yourself.
127
127
 
128
128
  The block parameter is a nested hash of the form input.
129
129
 
@@ -830,7 +830,7 @@ If you want full support for `simple_form` do as follows.
830
830
 
831
831
  ```ruby
832
832
  class SongForm < Reform::Form
833
- include ModelReflections
833
+ include ActiveModel::ModelReflections
834
834
  ```
835
835
 
836
836
  Including this module will add `#column_for_attribute` and other methods need by form builders to automatically guess the type of a property.
Binary file
@@ -4,13 +4,13 @@ module Reform
4
4
  end
5
5
  end
6
6
 
7
- require 'reform/contract'
8
- require 'reform/form'
9
- require 'reform/form/composition'
10
- require 'reform/form/active_model'
11
- require 'reform/form/module'
7
+ require "reform/contract"
8
+ require "reform/form"
9
+ require "reform/form/composition"
10
+ require "reform/form/active_model"
11
+ require "reform/form/module"
12
12
 
13
13
 
14
- if defined?(Rails) # DISCUSS: is everyone ok with this?
15
- require 'reform/rails'
14
+ if defined?(Rails)
15
+ require "reform/rails"
16
16
  end
@@ -1,4 +1,4 @@
1
- require 'reform/form/active_model'
2
- require 'reform/form/orm'
3
- require 'reform/form/active_record'
4
- require 'reform/form/model_reflections' # only load this in AR context as simple_form currently is bound to AR.
1
+ require "reform/form/active_model"
2
+ require "reform/form/orm"
3
+ require "reform/form/active_record"
4
+ require "reform/form/active_model/model_reflections" # only load this in AR context as simple_form currently is bound to AR.
@@ -1,19 +1,18 @@
1
- require 'forwardable'
2
- require 'uber/inheritable_attr'
3
- require 'uber/delegates'
1
+ require "uber/inheritable_attr"
2
+ require "disposable/twin"
3
+ require "disposable/twin/setup"
4
+ require "disposable/twin/default"
4
5
 
5
6
  module Reform
6
- # Gives you a DSL for defining the object structure and its validations.
7
- require "disposable/twin"
8
- require "disposable/twin/setup"
7
+ # Define your form structure and its validations. Instantiate it with a model,
8
+ # and then +validate+ this object graph.
9
9
  class Contract < Disposable::Twin
10
10
  require "disposable/twin/composition" # Expose.
11
11
  include Expose
12
12
 
13
13
  feature Setup
14
14
  feature Setup::SkipSetter
15
-
16
- extend Uber::Delegates
15
+ feature Default
17
16
 
18
17
  representer_class.instance_eval do
19
18
  def default_inline_class
@@ -57,10 +56,11 @@ module Reform
57
56
  _name = definition.name
58
57
  mod.instance_eval do
59
58
  @_name = _name.singularize.camelize
60
- def name # this adds Form::name for AM::Validations and I18N. i know it's retarded.
61
- # something weird happens here: somewhere in Rails, this creates a constant (e.g. User). if this name doesn't represent a valid
62
- # constant, the reloading in dev will fail with weird messages. i'm not sure if we should just get rid of Rails validations etc.
63
- # or if i should look into this?
59
+ # this adds Form::name for AM::Validations and I18N.
60
+ # i have a feeling that this is also needed for Rails autoloader, which is scary.
61
+ # beside that, it is a nice way for debugging to find out which anonymous form class you're working on:
62
+ # anonymous_nested_form.class.name
63
+ def name
64
64
  @_name
65
65
  end
66
66
  end
@@ -76,6 +76,7 @@ module Reform
76
76
  self.class.options_for(name)
77
77
  end
78
78
  end
79
+
79
80
  def self.options_for(name)
80
81
  representer_class.representable_attrs.get(name)
81
82
  end
@@ -12,7 +12,7 @@ module Reform::Contract::Validate
12
12
  valid? # calls AM/Lotus validators and invokes self.errors=.
13
13
 
14
14
  errors.merge!(self.errors, prefix) # local errors.
15
- errors.merge!(nested_errors, []) #
15
+ errors.merge!(nested_errors, [])
16
16
  end
17
17
 
18
18
  def errors
@@ -9,12 +9,13 @@ module Reform
9
9
  end
10
10
 
11
11
  require "reform/form/validate"
12
- include Validate # extend Contract#validate with additional behaviour.
12
+ include Validate # override Contract#validate with additional behaviour.
13
13
 
14
14
  require "reform/form/populator"
15
15
 
16
16
  module Property
17
- # add macro logic, e.g. for :populator.
17
+ # Add macro logic, e.g. for :populator.
18
+ # TODO: This will be re-structured once Declarative allows it.
18
19
  def property(name, options={}, &block)
19
20
  if deserializer = options[:deserializer] # this means someone is explicitly specifying :deserializer.
20
21
  options[:deserializer] = Representable::Cloneable::Hash[deserializer]
@@ -23,25 +24,18 @@ module Reform
23
24
  definition = super # let representable sort out inheriting of properties, and so on.
24
25
  definition.merge!(deserializer: Representable::Cloneable::Hash.new) unless definition[:deserializer] # always keep :deserializer per property.
25
26
 
26
-
27
27
  deserializer_options = definition[:deserializer]
28
28
 
29
- # TODO: make this pluggable.
30
- # DISCUSS: Populators should be a representable concept?
31
-
32
29
  # Populators
33
30
  # * they assign created data, no :setter (hence the name).
34
31
  # * they (ab)use :instance, this is why they need to return a twin form.
35
32
  # * they are only used in the deserializer.
36
-
37
-
38
-
39
33
  if populator = options.delete(:populate_if_empty)
40
34
  deserializer_options.merge!({instance: Populator::IfEmpty.new(populator)})
41
35
  deserializer_options.merge!({setter: nil})
42
36
  elsif populator = options.delete(:populator)
43
37
  deserializer_options.merge!({instance: Populator.new(populator)})
44
- deserializer_options.merge!({setter: nil}) #if options[:collection] # collections don't need to get re-assigned, they don't change.
38
+ deserializer_options.merge!({setter: nil})
45
39
  end
46
40
 
47
41
 
@@ -1,55 +1,14 @@
1
- require 'reform/form/active_model/model_validations'
1
+ require "reform/form/active_model/model_validations"
2
+ require "reform/form/active_model/form_builder_methods"
3
+ require "uber/delegates"
2
4
 
3
5
  module Reform::Form::ActiveModel
4
- module FormBuilderMethods # TODO: rename to FormBuilderCompat.
5
- def self.included(base)
6
- base.extend ClassMethods # ::model_name
7
- end
8
-
9
- module ClassMethods
10
- private
11
-
12
- # TODO: add that shit in Form#present, not by overriding ::property.
13
- def property(name, options={}, &block)
14
- super.tap do |definition|
15
- add_nested_attribute_compat(name) if definition[:twin] # TODO: fix that in Rails FB#1832 work.
16
- end
17
- end
18
-
19
- # The Rails FormBuilder "detects" nested attributes (which is what we want) by checking existance of a setter method.
20
- def add_nested_attribute_compat(name)
21
- define_method("#{name}_attributes=") {} # this is why i hate respond_to? in Rails.
22
- end
23
- end
24
-
25
- # Modify the incoming Rails params hash to be representable compliant.
26
- def deserialize!(params)
27
- # this only happens in a Hash environment. other engines have to overwrite this method.
28
- schema.each do |dfn|
29
- rename_nested_param_for!(params, dfn)
30
- end
31
-
32
- super(params)
33
- end
34
-
35
- private
36
- def rename_nested_param_for!(params, dfn)
37
- nested_name = "#{dfn.name}_attributes"
38
- return unless params.has_key?(nested_name)
39
-
40
- value = params["#{dfn.name}_attributes"]
41
- value = value.values if dfn[:collection]
42
-
43
- params[dfn.name] = value
44
- end
45
- end # FormBuilderMethods
46
-
47
-
48
6
  def self.included(base)
49
7
  base.class_eval do
50
8
  extend ClassMethods
51
9
  register_feature ActiveModel
52
10
 
11
+ extend Uber::Delegates
53
12
  delegates :model, *[:persisted?, :to_key, :to_param, :id] # Uber::Delegates
54
13
 
55
14
  def to_model # this is called somewhere in FormBuilder and ActionController.
@@ -0,0 +1,47 @@
1
+ module Reform::Form::ActiveModel
2
+ # Including FormBuilderMethods will allow using form instances with form_for, simple_form, etc.
3
+ # in Rails. It will further try to translate Rails' suboptimal songs_attributes weirdness
4
+ # back to normal `songs: ` naming in +#valiate+.
5
+ module FormBuilderMethods
6
+ def self.included(base)
7
+ base.extend ClassMethods # ::model_name
8
+ end
9
+
10
+ module ClassMethods
11
+ private
12
+
13
+ # TODO: add that shit in Form#present, not by overriding ::property.
14
+ def property(name, options={}, &block)
15
+ super.tap do |definition|
16
+ add_nested_attribute_compat(name) if definition[:twin] # TODO: fix that in Rails FB#1832 work.
17
+ end
18
+ end
19
+
20
+ # The Rails FormBuilder "detects" nested attributes (which is what we want) by checking existance of a setter method.
21
+ def add_nested_attribute_compat(name)
22
+ define_method("#{name}_attributes=") {} # this is why i hate respond_to? in Rails.
23
+ end
24
+ end
25
+
26
+ # Modify the incoming Rails params hash to be representable compliant.
27
+ def deserialize!(params)
28
+ # this only happens in a Hash environment. other engines have to overwrite this method.
29
+ schema.each do |dfn|
30
+ rename_nested_param_for!(params, dfn)
31
+ end
32
+
33
+ super(params)
34
+ end
35
+
36
+ private
37
+ def rename_nested_param_for!(params, dfn)
38
+ nested_name = "#{dfn.name}_attributes"
39
+ return unless params.has_key?(nested_name)
40
+
41
+ value = params["#{dfn.name}_attributes"]
42
+ value = value.values if dfn[:collection]
43
+
44
+ params[dfn.name] = value
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ # ModelReflections will be the interface between the form object and form builders like simple_form.
2
+ #
3
+ # This module is meant to collect all dependencies simple_form needs in addition to the ActiveModel ones.
4
+ # Goal is to collect all methods and define a reflection API so simple_form works with all ORMs and Reform
5
+ # doesn't have to "guess" what simple_form and other form helpers need.
6
+ class Reform::Form < Reform::Contract
7
+ module ActiveModel::ModelReflections
8
+ def self.included(base)
9
+ base.extend ClassMethods
10
+ base.register_feature self # makes it work in nested forms.
11
+ end
12
+
13
+ module ClassMethods
14
+ # Delegate reflect_on_association to the model class to support simple_form's
15
+ # association input.
16
+ def reflect_on_association(*args)
17
+ model_name.to_s.constantize.reflect_on_association(*args)
18
+ end
19
+ end
20
+
21
+ # Delegate column for attribute to the model to support simple_form's
22
+ # attribute type interrogation.
23
+ def column_for_attribute(name)
24
+ model_for_property(name).column_for_attribute(name)
25
+ end
26
+
27
+ def has_attribute?(name)
28
+ model_for_property(name).has_attribute?(name)
29
+ end
30
+
31
+ def defined_enums
32
+ return model.defined_enums unless is_a?(Reform::Form::Composition)
33
+
34
+ mapper.each.with_object({}) { |m,h| h.merge! m.defined_enums }
35
+ end
36
+
37
+ # this should also contain to_param and friends as this is used by the form helpers.
38
+ end
39
+
40
+ ModelReflections = ActiveModel::ModelReflections
41
+ end
@@ -1,5 +1,6 @@
1
1
  require "active_model"
2
- require "reform/contract/errors"
2
+ require "reform/form/active_model/errors"
3
+ require "uber/delegates"
3
4
 
4
5
  module Reform::Form::ActiveModel
5
6
  # AM::Validations for your form.
@@ -30,6 +31,8 @@ module Reform::Form::ActiveModel
30
31
  # Validators is the validatable object. On the class level, we define validations,
31
32
  # on instance, it exposes #valid?.
32
33
  class Validator
34
+ # current i18n scope: :activemodel.
35
+
33
36
  include ActiveModel::Validations
34
37
  # extend ActiveModel::Naming
35
38
 
@@ -1,5 +1,3 @@
1
1
  require "disposable/twin/coercion"
2
2
 
3
- Reform::Form.class_eval do
4
- Coercion = Disposable::Twin::Coercion
5
- end
3
+ Reform::Form::Coercion = Disposable::Twin::Coercion
@@ -2,7 +2,7 @@ module Reform::Form::ORM
2
2
  def model_for_property(name)
3
3
  return model unless is_a?(Reform::Form::Composition) # i am too lazy for proper inheritance. there should be a ActiveRecord::Composition that handles this.
4
4
 
5
- model_name = schema.representable_attrs.get(name)[:on]
5
+ model_name = options_for(name)[:on]
6
6
  model[model_name]
7
7
  end
8
8
 
@@ -1,5 +1,3 @@
1
- # TODO: move somewhere else!
2
- # TODO: make inheritable? and also, there's a lot of noise. shorten.
3
1
  # Implements the :populator option.
4
2
  #
5
3
  # populator: -> (fragment, twin, options)
@@ -5,8 +5,7 @@ module Reform::Form::Validate
5
5
  include Uber::Callable
6
6
 
7
7
  def call(form, params, options)
8
- # TODO: hahahahahaha.
9
- # FIXME: this is a bit ridiculous.
8
+ # TODO: Schema should provide property names as plain list.
10
9
  properties = options.binding[:twin].representer_class.representable_attrs[:definitions].keys
11
10
 
12
11
  properties.each { |name| params[name].present? and return false }
@@ -46,7 +45,7 @@ private
46
45
  # DISCUSS: this is only called once, on the top-level form.
47
46
  def deprecate_update!(params)
48
47
  return unless self.class.instance_methods(false).include?(:update!)
49
- warn "[Reform] Form#update! is deprecated and will be removed in Reform 2.1. Please use #present! or pre-populator."
48
+ warn "[Reform] Form#update! is deprecated and will be removed in Reform 2.1. Please use #prepopulate!"
50
49
  update!(params)
51
50
  end
52
51
 
@@ -68,7 +67,6 @@ private
68
67
 
69
68
  deserializer.apply do |dfn|
70
69
  next unless dfn[:twin]
71
-
72
70
  # Representer#each and #apply have to be unified.
73
71
  dfn.merge!(
74
72
  deserialize: lambda { |decorator, params, options|
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "2.0.0.rc3"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "disposable", "~> 0.1.5"
20
+ spec.add_dependency "disposable", "~> 0.1.7"
21
21
  spec.add_dependency "uber", "~> 0.0.11"
22
22
 
23
23
  spec.add_development_dependency "bundler"
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ class DefaultTest < Minitest::Spec
4
+ Song = Struct.new(:title, :album, :composer)
5
+ Album = Struct.new(:name, :songs, :artist)
6
+ Artist = Struct.new(:name)
7
+
8
+ class AlbumForm < Reform::Form
9
+ property :name, default: "Wrong"
10
+
11
+ collection :songs do
12
+ property :title, default: "It's Catching Up"
13
+ end
14
+ end
15
+
16
+ it do
17
+ form = AlbumForm.new(Album.new(nil, [Song.new]))
18
+
19
+ form.name.must_equal "Wrong"
20
+ form.songs[0].title.must_equal "It's Catching Up"
21
+ end
22
+ end
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'reform/form/json'
3
2
 
4
3
  class DeserializeTest < MiniTest::Spec
5
4
  Song = Struct.new(:title, :album, :composer)
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
  class ModelReflectionTest < MiniTest::Spec
5
5
  class SongForm < Reform::Form
6
6
  include Reform::Form::ActiveRecord
7
- include Reform::Form::ModelReflections
7
+ include Reform::Form::ActiveModel::ModelReflections
8
8
 
9
9
  model :song
10
10
 
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: 2.0.0.rc3
4
+ version: 2.0.0
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: 2015-07-08 00:00:00.000000000 Z
12
+ date: 2015-07-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: disposable
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 0.1.5
20
+ version: 0.1.7
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
- version: 0.1.5
27
+ version: 0.1.7
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: uber
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -205,32 +205,29 @@ files:
205
205
  - lib/reform.rb
206
206
  - lib/reform/active_record.rb
207
207
  - lib/reform/contract.rb
208
- - lib/reform/contract/errors.rb
209
208
  - lib/reform/contract/validate.rb
210
209
  - lib/reform/form.rb
211
210
  - lib/reform/form/active_model.rb
211
+ - lib/reform/form/active_model/errors.rb
212
+ - lib/reform/form/active_model/form_builder_methods.rb
213
+ - lib/reform/form/active_model/model_reflections.rb
212
214
  - lib/reform/form/active_model/model_validations.rb
213
215
  - lib/reform/form/active_model/validations.rb
214
216
  - lib/reform/form/active_record.rb
215
217
  - lib/reform/form/coercion.rb
216
218
  - lib/reform/form/composition.rb
217
- - lib/reform/form/json.rb
218
219
  - lib/reform/form/lotus.rb
219
- - lib/reform/form/model_reflections.rb
220
220
  - lib/reform/form/module.rb
221
221
  - lib/reform/form/mongoid.rb
222
222
  - lib/reform/form/multi_parameter_attributes.rb
223
223
  - lib/reform/form/orm.rb
224
224
  - lib/reform/form/populator.rb
225
225
  - lib/reform/form/prepopulate.rb
226
- - lib/reform/form/save.rb
227
- - lib/reform/form/scalar.rb
228
226
  - lib/reform/form/validate.rb
229
227
  - lib/reform/form/validation/unique_validator.rb
230
228
  - lib/reform/mongoid.rb
231
229
  - lib/reform/rails.rb
232
230
  - lib/reform/schema.rb
233
- - lib/reform/twin.rb
234
231
  - lib/reform/version.rb
235
232
  - reform.gemspec
236
233
  - test/active_model_test.rb
@@ -242,6 +239,7 @@ files:
242
239
  - test/composition_test.rb
243
240
  - test/contract_test.rb
244
241
  - test/custom_validation_test.rb
242
+ - test/default_test.rb
245
243
  - test/deserialize_test.rb
246
244
  - test/dummy/Rakefile
247
245
  - test/dummy/app/controllers/albums_controller.rb
@@ -292,7 +290,6 @@ files:
292
290
  - test/skip_if_test.rb
293
291
  - test/skip_setter_and_getter_test.rb
294
292
  - test/test_helper.rb
295
- - test/twin_test.rb
296
293
  - test/unique_test.rb
297
294
  - test/validate_test.rb
298
295
  - test/virtual_test.rb
@@ -312,9 +309,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
312
309
  version: '0'
313
310
  required_rubygems_version: !ruby/object:Gem::Requirement
314
311
  requirements:
315
- - - ">"
312
+ - - ">="
316
313
  - !ruby/object:Gem::Version
317
- version: 1.3.1
314
+ version: '0'
318
315
  requirements: []
319
316
  rubyforge_project:
320
317
  rubygems_version: 2.4.8
@@ -331,6 +328,7 @@ test_files:
331
328
  - test/composition_test.rb
332
329
  - test/contract_test.rb
333
330
  - test/custom_validation_test.rb
331
+ - test/default_test.rb
334
332
  - test/deserialize_test.rb
335
333
  - test/dummy/Rakefile
336
334
  - test/dummy/app/controllers/albums_controller.rb
@@ -381,7 +379,6 @@ test_files:
381
379
  - test/skip_if_test.rb
382
380
  - test/skip_setter_and_getter_test.rb
383
381
  - test/test_helper.rb
384
- - test/twin_test.rb
385
382
  - test/unique_test.rb
386
383
  - test/validate_test.rb
387
384
  - test/virtual_test.rb
@@ -1,13 +0,0 @@
1
- require 'representable/json'
2
-
3
- module Reform
4
- module Form::JSON
5
- def self.included(base)
6
- base.representer_class.send :include, Representable::JSON
7
- end
8
-
9
- def deserialize_method
10
- :from_json
11
- end
12
- end
13
- end
@@ -1,37 +0,0 @@
1
- # ModelReflections will be the interface between the form object and form builders like simple_form.
2
- #
3
- # This module is meant to collect all dependencies simple_form needs in addition to the ActiveModel ones.
4
- # Goal is to collect all methods and define a reflection API so simple_form works with all ORMs and Reform
5
- # doesn't have to "guess" what simple_form and other form helpers need.
6
- module Reform::Form::ModelReflections
7
- def self.included(base)
8
- base.extend ClassMethods
9
- base.register_feature self # makes it work in nested forms.
10
- end
11
-
12
- module ClassMethods
13
- # Delegate reflect_on_association to the model class to support simple_form's
14
- # association input.
15
- def reflect_on_association(*args)
16
- model_name.to_s.constantize.reflect_on_association(*args)
17
- end
18
- end
19
-
20
- # Delegate column for attribute to the model to support simple_form's
21
- # attribute type interrogation.
22
- def column_for_attribute(name)
23
- model_for_property(name).column_for_attribute(name)
24
- end
25
-
26
- def has_attribute?(name)
27
- model_for_property(name).has_attribute?(name)
28
- end
29
-
30
- def defined_enums
31
- return model.defined_enums unless is_a?(Reform::Form::Composition)
32
-
33
- mapper.each.with_object({}) { |m,h| h.merge! m.defined_enums }
34
- end
35
-
36
- # this should also contain to_param and friends as this is used by the form helpers.
37
- end
@@ -1,66 +0,0 @@
1
- module Reform::Form::Save
2
- # Returns the result of that save invocation on the model.
3
- def save(options={}, &block)
4
- # DISCUSS: we should never hit @mapper here (which writes to the models) when a block is passed.
5
- return yield to_nested_hash if block_given?
6
-
7
- sync_models # recursion
8
- save!(options)
9
- end
10
-
11
- def save!(options={}) # FIXME.
12
- result = save_model
13
-
14
- save_representer.new(fields).to_hash # save! on all nested forms.
15
-
16
- dynamic_save!(options)
17
-
18
- result
19
- end
20
-
21
- def save_model
22
- model.save # TODO: implement nested (that should really be done by Twin/AR).
23
- end
24
-
25
-
26
- require "active_support/hash_with_indifferent_access" # DISCUSS: replace?
27
- def to_nested_hash(*)
28
- ActiveSupport::HashWithIndifferentAccess.new(nested_hash_representer.new(fields).to_hash)
29
- end
30
- alias_method :to_hash, :to_nested_hash
31
- # NOTE: it is not recommended using #to_hash and #to_nested_hash in your code, consider them private.
32
-
33
- private
34
- def save_representer
35
- self.class.representer(:save) do |dfn|
36
- dfn.merge!(
37
- :instance => lambda { |form, *| form },
38
- :serialize => lambda { |form, args| form.save! unless args.binding[:save] === false }
39
- )
40
- end
41
- end
42
-
43
- def nested_hash_representer
44
- self.class.representer(:nested_hash, :all => true) do |dfn|
45
- dfn.merge!(:serialize => lambda { |form, args| form.to_nested_hash }) if dfn[:form]
46
-
47
- dfn.merge!(:as => dfn[:private_name] || dfn.name)
48
- end
49
- end
50
-
51
- def dynamic_save!(options)
52
- names = options.keys & changed.keys.map(&:to_sym)
53
- return if names.size == 0
54
-
55
- dynamic_save_representer.new(fields).to_hash(options.merge(:include => names))
56
- end
57
-
58
- def dynamic_save_representer
59
- self.class.representer(:dynamic_save, :all => true) do |dfn|
60
- dfn.merge!(
61
- :serialize => lambda { |object, options| options.user_options[options.binding.name.to_sym].call(object, options) },
62
- :representable => true
63
- )
64
- end
65
- end
66
- end
@@ -1,54 +0,0 @@
1
- module Reform::Form::Scalar
2
- # IDEA: what if every "leaf" property would be represented by a Scalar form?
3
- def self.included(base)
4
- base.extend ClassMethods
5
- base.extend Forwardable
6
- end
7
-
8
- def update!(object)
9
- @fields = object # @scalar is "I came from the outside." or <ArbitraryObject>.
10
- end
11
-
12
- def scalar
13
- fields
14
- end
15
-
16
- def save!
17
- end
18
-
19
- def sync!(*)
20
- model.replace(fields)
21
- # FIXME: how to sync that, if it's not responds to replace? or what if we don't want to write (e.g. image with paperdragon)?
22
- end
23
-
24
- def to_nested_hash
25
- scalar
26
- end
27
-
28
-
29
- module ClassMethods
30
- def validates(name, options={})
31
- if name.is_a?(Hash)
32
- name, options = :scalar, name # per default, validate #scalar (e.g. "Hello").
33
- else
34
- def_delegator :scalar, name
35
- end
36
-
37
- super(name, options)
38
- end
39
- end
40
-
41
-
42
- # TODO: change the way i hook into ::property.
43
- module Property
44
- private
45
-
46
- def property(name, options={}, &block)
47
- if options[:scalar]
48
- options.merge!(:features => [Reform::Form::Scalar], populate_if_empty: String)
49
- end
50
-
51
- super
52
- end
53
- end
54
- end
@@ -1,20 +0,0 @@
1
- require 'disposable/twin'
2
-
3
- module Reform
4
- module Twin
5
- def self.included(base)
6
- base.send :include, Disposable::Twin::Builder
7
- base.extend ClassMethods
8
- end
9
-
10
- module ClassMethods
11
- def twin(twin_class)
12
- super(twin_class) { |dfn| property dfn.name } # create readers to twin model.
13
- end
14
- end
15
-
16
- def initialize(model, options={})
17
- super(build_twin(model, options))
18
- end
19
- end
20
- end
@@ -1,38 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'test_helper'
4
- require 'reform/twin'
5
-
6
- # class TwinTest < MiniTest::Spec
7
- # class SongForm < Reform::Form
8
- # class Twin < Disposable::Twin
9
- # property :title
10
- # option :is_online # TODO: this should make it read-only in reform!
11
- # end
12
-
13
- # # include Reform::Twin
14
- # # twin Twin
15
- # end
16
-
17
- # let (:model) { OpenStruct.new(title: "Kenny") }
18
-
19
- # let (:form) { SongForm.new(model, is_online: true) }
20
-
21
- # it { form.title.must_equal "Kenny" }
22
- # it { form.is_online.must_equal true }
23
- # end
24
- class TwinTest < MiniTest::Spec
25
- Song = Struct.new(:name)
26
-
27
- class SongForm < Reform::Form
28
- property :name
29
- property :is_online, virtual: true
30
- end
31
-
32
- let (:form) { SongForm.new(Song.new("Kenny"), is_online: true) }
33
-
34
- it do
35
- form.name.must_equal "Kenny"
36
- form.is_online.must_equal true
37
- end
38
- end