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 +4 -4
- data/CHANGES.md +15 -8
- data/README.md +2 -2
- data/database.sqlite3 +0 -0
- data/lib/reform.rb +7 -7
- data/lib/reform/active_record.rb +4 -4
- data/lib/reform/contract.rb +13 -12
- data/lib/reform/contract/validate.rb +1 -1
- data/lib/reform/form.rb +4 -10
- data/lib/reform/form/active_model.rb +4 -45
- data/lib/reform/{contract → form/active_model}/errors.rb +0 -0
- data/lib/reform/form/active_model/form_builder_methods.rb +47 -0
- data/lib/reform/form/active_model/model_reflections.rb +41 -0
- data/lib/reform/form/active_model/validations.rb +4 -1
- data/lib/reform/form/coercion.rb +1 -3
- data/lib/reform/form/orm.rb +1 -1
- data/lib/reform/form/populator.rb +0 -2
- data/lib/reform/form/validate.rb +2 -4
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +1 -1
- data/test/default_test.rb +22 -0
- data/test/deserialize_test.rb +0 -1
- data/test/model_reflections_test.rb +1 -1
- metadata +11 -14
- data/lib/reform/form/json.rb +0 -13
- data/lib/reform/form/model_reflections.rb +0 -37
- data/lib/reform/form/save.rb +0 -66
- data/lib/reform/form/scalar.rb +0 -54
- data/lib/reform/twin.rb +0 -20
- data/test/twin_test.rb +0 -38
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 247ffc53838f5e69a71f4ab5d066572b05308003
|
|
4
|
+
data.tar.gz: f6162c6a018e02ad2f9c487441dcea08623b960a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
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.
|
data/database.sqlite3
CHANGED
|
Binary file
|
data/lib/reform.rb
CHANGED
|
@@ -4,13 +4,13 @@ module Reform
|
|
|
4
4
|
end
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
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)
|
|
15
|
-
require
|
|
14
|
+
if defined?(Rails)
|
|
15
|
+
require "reform/rails"
|
|
16
16
|
end
|
data/lib/reform/active_record.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
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.
|
data/lib/reform/contract.rb
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
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
|
-
#
|
|
7
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
data/lib/reform/form.rb
CHANGED
|
@@ -9,12 +9,13 @@ module Reform
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
require "reform/form/validate"
|
|
12
|
-
include Validate #
|
|
12
|
+
include Validate # override Contract#validate with additional behaviour.
|
|
13
13
|
|
|
14
14
|
require "reform/form/populator"
|
|
15
15
|
|
|
16
16
|
module Property
|
|
17
|
-
#
|
|
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})
|
|
38
|
+
deserializer_options.merge!({setter: nil})
|
|
45
39
|
end
|
|
46
40
|
|
|
47
41
|
|
|
@@ -1,55 +1,14 @@
|
|
|
1
|
-
require
|
|
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.
|
|
File without changes
|
|
@@ -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/
|
|
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
|
|
data/lib/reform/form/coercion.rb
CHANGED
data/lib/reform/form/orm.rb
CHANGED
|
@@ -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 =
|
|
5
|
+
model_name = options_for(name)[:on]
|
|
6
6
|
model[model_name]
|
|
7
7
|
end
|
|
8
8
|
|
data/lib/reform/form/validate.rb
CHANGED
|
@@ -5,8 +5,7 @@ module Reform::Form::Validate
|
|
|
5
5
|
include Uber::Callable
|
|
6
6
|
|
|
7
7
|
def call(form, params, options)
|
|
8
|
-
# TODO:
|
|
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 #
|
|
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|
|
data/lib/reform/version.rb
CHANGED
data/reform.gemspec
CHANGED
|
@@ -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.
|
|
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
|
data/test/deserialize_test.rb
CHANGED
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
|
|
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-
|
|
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.
|
|
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.
|
|
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:
|
|
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
|
data/lib/reform/form/json.rb
DELETED
|
@@ -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
|
data/lib/reform/form/save.rb
DELETED
|
@@ -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
|
data/lib/reform/form/scalar.rb
DELETED
|
@@ -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
|
data/lib/reform/twin.rb
DELETED
|
@@ -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
|
data/test/twin_test.rb
DELETED
|
@@ -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
|