reform 2.0.0.beta1 → 2.0.0.beta2

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: 719c0d3aec98a161756c38012b620944cf19fa22
4
- data.tar.gz: f7adb9cb663ea890809b3606a3ab01376fe4453d
3
+ metadata.gz: 4b89a50eb51cda0fe932efa6b7e67eb03658fdba
4
+ data.tar.gz: 019bfd72b5e2c966dde1a35bc22ce4dc0c2bd934
5
5
  SHA512:
6
- metadata.gz: 78d3c8711d9a337ca128e6e0cf14ebfe4df94230c4e1180110bd419ef7d4d0951be2a5f3823be807e2daf68f483a02f149e8bea212bfcac7d59613a115fbabc3
7
- data.tar.gz: 9434d975625b3719bcd47a1a31da9be8feda733c3af43a78237fdbe1fa5e90805cefb88e9e707ec4c9f050a2615a1626ae345477076d1b235c9107f9c388f8cd
6
+ metadata.gz: adb468e4594747b200c08ac1e23dcefab0730e801698f4fd2e675a04366f75fdd156a4bc3f49fd571f0346ae7283397e5b7cf7ab536243abbd2e6e70883248a2
7
+ data.tar.gz: 20aab2ce543b0619ee7e064e11c993d58792cb030af05513361b358ba9b324aaf0d24bf500edadaa1dbb1f08cac18aae20d6bfe0e68b1ce86cbbe43fc1a02fb4
data/CHANGES.md CHANGED
@@ -11,6 +11,7 @@ you don't need to know about forms anymore, the twin handles that using #insert.
11
11
 
12
12
  * `:as` option removed. Use `:from`.
13
13
  * With `Composition` included, `Form#model` would give you a composition object. You can grab that using `Form#mapper` now.
14
+ * `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".
14
15
 
15
16
  ## 1.2.6
16
17
 
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  #gem 'representable', path: "../representable"
6
- gem "disposable", path: "../disposable"
6
+ # gem "disposable", path: "../disposable"
7
7
  # gem "disposable", github: "apotonick/disposable"
data/README.md CHANGED
@@ -859,6 +859,30 @@ form.changed?(:title) #=> true
859
859
  When including `Sync::SkipUnchanged`, the form won't assign unchanged values anymore in `#sync`.
860
860
 
861
861
 
862
+ ## Deserializing and Population
863
+
864
+ A form object is just a twin. In `validate`, a representer is used to deserialize the incoming hash and populate the form twin graph. This means, you can use any representer you like and process data like JSON or XML, too.
865
+
866
+ Representers can be inferred from the contract automatically using `Disposable::Schema`. You may then extend your representer with hypermedia, etc. in order to render documents. Check out the Trailblazer book (chapter Hypermedia APIs) for a full explanation.
867
+
868
+ You can even write your own deserializer code in case you dislike Representable.
869
+
870
+ ```ruby
871
+ class AlbumForm < Reform::Form
872
+ # ..
873
+
874
+ def deserialize!(document)
875
+ hash = YAML.parse(document)
876
+
877
+ self.title = hash[:title]
878
+ self.artist = Artist.new if hash[:artist]
879
+ end
880
+ end
881
+ ```
882
+
883
+ The decoupling of deserializer and form object is one of the main reasons I wrote Reform 2.
884
+
885
+
862
886
  ## Undocumented Features
863
887
 
864
888
  _(Please don't read this section!)_
@@ -941,7 +965,6 @@ If you run into any trouble chat with us on irc.freenode.org#trailblazer.
941
965
  ## Maintainers
942
966
 
943
967
  [Nick Sutterer](https://github.com/apotonick)
944
-
945
968
  [Garrett Heinlen](https://github.com/gogogarrett)
946
969
 
947
970
 
data/Rakefile CHANGED
@@ -27,7 +27,9 @@ Rake::TestTask.new(:test) do |test|
27
27
  "test/uniqueness_test.rb",
28
28
  "test/from_test.rb",
29
29
  "test/composition_test.rb",
30
- "test/form_option_test.rb"
30
+ "test/form_option_test.rb",
31
+ "test/form_test.rb",
32
+ "test/deserialize_test.rb"
31
33
  ]
32
34
 
33
35
 
Binary file
@@ -5,4 +5,3 @@ gemspec :path => '../'
5
5
 
6
6
  gem 'railties', '~> 3.0.11'
7
7
  gem 'activerecord', '~> 3.0.11'
8
- gem "disposable", github: "apotonick/disposable"
@@ -5,4 +5,3 @@ gemspec :path => '../'
5
5
 
6
6
  gem 'railties', '~> 3.1.0'
7
7
  gem 'activerecord', '~> 3.1.0'
8
- gem "disposable", github: "apotonick/disposable"
@@ -5,4 +5,3 @@ gemspec :path => '../'
5
5
 
6
6
  gem 'railties', '~> 3.2.0'
7
7
  gem 'activerecord', '~> 3.2.0'
8
- gem "disposable", github: "apotonick/disposable"
@@ -6,4 +6,3 @@ gemspec :path => '../'
6
6
  gem 'railties', '~> 4.0.0'
7
7
  gem 'activerecord', '~> 4.0.0'
8
8
  gem 'minitest', '~> 4.2'
9
- gem "disposable", github: "apotonick/disposable"
@@ -15,12 +15,6 @@ module Reform
15
15
 
16
16
  extend Uber::Delegates
17
17
 
18
- representer_class.instance_eval do
19
- def default_inline_class
20
- Contract
21
- end
22
- end
23
- # FIXME: THIS sucks because we're building two representers.
24
18
  representer_class.instance_eval do
25
19
  def default_inline_class
26
20
  Contract
@@ -28,19 +22,21 @@ module Reform
28
22
  end
29
23
 
30
24
  def self.property(name, options={}, &block)
31
- options.merge!(pass_options: true)
32
-
33
25
  if twin = options.delete(:form)
34
26
  options[:twin] = twin
35
27
  end
36
28
 
29
+ if validates_options = options[:validates]
30
+ validates name, validates_options.dup # .dup for RAils 3.x because it's retarded.
31
+ end
32
+
37
33
  super
38
34
  end
39
35
 
40
36
  # FIXME: test me.
41
37
  def self.properties(*args)
42
38
  options = args.extract_options!
43
- args.each { |name| property(name, options.dup) }
39
+ args.each { |name| property(name, options) }
44
40
  end
45
41
 
46
42
  # FIXME: make AM optional.
@@ -91,17 +87,12 @@ module Reform
91
87
  def self.clone # TODO: test. THIS IS ONLY FOR Trailblazer when contract gets cloned in suboperation.
92
88
  Class.new(self)
93
89
  end
90
+
91
+ require "reform/schema"
92
+ extend Reform::Schema
94
93
  end
95
94
 
96
95
  class Contract_ # DISCUSS: make class?
97
- extend Uber::InheritableAttr
98
-
99
- RESERVED_METHODS = [:model] # TODO: refactor that so we don't need that.
100
- def handle_reserved_names(name)
101
- raise "[Reform] the property name '#{name}' is reserved, please consider something else using :as." if RESERVED_METHODS.include?(name)
102
- end
103
-
104
-
105
96
  # allows including representers from Representable, Roar or disposable.
106
97
  def self.inherit_module!(representer) # called from Representable::included.
107
98
  # representer_class.inherit_module!(representer)
@@ -115,9 +106,6 @@ module Reform
115
106
  property(*args) { include dfn.representer_module } # nested.
116
107
  end
117
108
  end
118
-
119
- require 'reform/schema'
120
- extend Schema
121
109
  end
122
110
  end
123
111
 
@@ -1,3 +1,5 @@
1
+ require "disposable/twin/schema"
2
+
1
3
  module Reform
2
4
  class Form < Contract
3
5
  representer_class.instance_eval do
@@ -85,4 +87,4 @@ module Reform
85
87
  require "reform/form/prepopulate"
86
88
  include Prepopulate
87
89
  end
88
- end
90
+ end
@@ -29,7 +29,7 @@ module Reform::Form::ActiveModel
29
29
  rename_nested_param_for!(params, dfn)
30
30
  end
31
31
 
32
- super
32
+ super(params)
33
33
  end
34
34
 
35
35
  private
@@ -1,5 +1,5 @@
1
- require 'representable/coercion'
1
+ require "disposable/twin/coercion"
2
2
 
3
- # TODO: make optional.
4
- module Reform::Form::Coercion
5
- end
3
+ Reform::Form.class_eval do
4
+ Coercion = Disposable::Twin::Coercion
5
+ end
@@ -38,8 +38,7 @@ module Reform::Form::MultiParameterAttributes
38
38
 
39
39
  # this hooks into the format-specific #deserialize! method.
40
40
  def deserialize!(params)
41
- params = DateTimeParamsFilter.new.call(params) if params.is_a?(Hash) # this currently works for hash, only.
42
- super
41
+ super DateTimeParamsFilter.new.call(params) # if params.is_a?(Hash) # this currently works for hash, only.
43
42
  end
44
43
 
45
44
  # module BuildDefinition
@@ -20,58 +20,69 @@ module Reform::Form::Validate
20
20
  # 2. Deserialize. This is wrong and should be done in 1.
21
21
  # 3. Validate the form object graph.
22
22
  def validate(params)
23
- update!(params)
23
+ deprecate_update!(params)
24
24
 
25
- super() # run the actual validation on self.
25
+ # allow an external deserializer.
26
+ block_given? ? yield(params) : deserialize(params)
26
27
 
28
+ super() # run the actual validation on self.
27
29
  # rescue Representable::DeserializeError
28
30
  # raise DeserializeError.new("[Reform] Deserialize error: You probably called #validate without setting up your nested models. Check https://github.com/apotonick/reform#populating-forms-for-validation on how to use populators.")
29
31
  end
30
32
 
33
+ # Meant to return params processable by the representer. This is the hook for munching date fields, etc.
34
+ def deserialize!(params)
35
+ # NOTE: it is completely up to the form user how they want to deserialize (e.g. using an external JSON-API representer).
36
+ # use the deserializer as an external instance to operate on the Twin API,
37
+ # e.g. adding new items in collections using #<< etc.
38
+ # DISCUSS: using self here will call the form's setters like title= which might be overridden.
39
+ params
40
+ end
41
+
42
+
43
+ private
31
44
  # Some users use this method to pre-populate a form. Not saying this is right, but we'll keep
32
45
  # this method here.
33
46
  # DISCUSS: this is only called once, on the top-level form.
34
- def update!(params)
35
- deserialize!(params)
47
+ def deprecate_update!(params)
48
+ 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."
50
+ update!(params)
36
51
  end
37
52
 
38
- private
39
- def deserialize!(params)
40
- require "disposable/twin/schema"
41
- require "reform/form/coercion" # DISCUSS: make optional?
53
+ def deserialize(params)
54
+ params = deserialize!(params)
42
55
 
43
- # NOTE: it is completely up to the form user how they want to deserialize (e.g. using an external JSON-API representer).
56
+ deserializer.new(self).from_hash(params)
57
+ end
44
58
 
59
+ # Default deserializer for hash.
60
+ # This is input-specific, e.g. Hash, JSON, or XML.
61
+ def deserializer # called on top-level, only, for now.
45
62
  deserializer = Disposable::Twin::Schema.from(self.class,
46
- include: [Representable::Hash::AllowSymbols, Representable::Hash, Representable::Coercion], # FIXME: how do we get this info?
47
- superclass: Representable::Decorator,
48
- representer_from: lambda { |inline| inline.representer_class },
49
- options_from: :deserializer
50
- )
63
+ include: [Representable::Hash::AllowSymbols, Representable::Hash],
64
+ superclass: Representable::Decorator,
65
+ representer_from: lambda { |inline| inline.representer_class },
66
+ options_from: :deserializer
67
+ )
51
68
 
52
- deserializer.representable_attrs.each do |dfn|
53
- next unless dfn[:_inline] # FIXME: we have to standardize that!
69
+ deserializer.apply do |dfn|
70
+ next unless dfn[:twin]
54
71
 
55
- # FIXME: collides with Schema?
72
+ # Representer#each and #apply have to be unified.
56
73
  dfn.merge!(
57
74
  deserialize: lambda { |decorator, params, options|
58
- decorator.represented.validate(params)
75
+ params = decorator.represented.deserialize!(params) # let them set up params. # FIXME: we could also get a new deserializer here.
59
76
 
60
- decorator.represented
77
+ decorator.from_hash(params) # options.binding.deserialize_method.inspect
61
78
  }
62
79
  )
63
80
  end
64
81
 
65
- deserializer.new(self).
66
- # extend(Representable::Debug).
67
- from_hash(params)
68
-
69
- # use the deserializer as an external instance to operate on the Twin API,
70
- # e.g. adding new items in collections using #<< etc.
71
-
72
- # DISCUSS: using self here will call the form's setters like title= which might be overridden.
82
+ deserializer
73
83
  end
74
84
 
85
+
75
86
  class DeserializeError < RuntimeError
76
87
  end
77
88
  end
@@ -1,27 +1,13 @@
1
1
  module Reform
2
2
  module Schema
3
- # Converts the Representer->Form->Representer->Form tree into Representer->Representer.
4
- # It becomes obvious that the form will be the main schema-defining instance in Trb, so this
5
- # method makes sense. Consider private. This is experimental.
6
- #
7
- # This allows generating representers from forms. As you can see, only little code is needed thanks to representable.
8
- class Converter
9
- def self.from(representer_class) # TODO: can we re-use this for all the decorator logic in #validate, etc?
10
- representer = Class.new(representer_class)
11
- representer.representable_attrs.each do |dfn|
12
- next unless form = dfn[:form]
13
-
14
- dfn.merge!(:extend => from(form.representer_class))
15
- dfn.delete!(:prepare) # not sure if this is gonna stay. also, this is representable 2.1, only.
16
- end
17
-
18
- representer
19
- end
20
- end
21
-
22
- # It's your job to make sure you memoize it correctly.
23
- def schema
24
- Converter.from(representer_class)
3
+ def schema(options={})
4
+ require "disposable/twin/schema"
5
+ Disposable::Twin::Schema.from(self,
6
+ {
7
+ superclass: Representable::Decorator,
8
+ representer_from: lambda { |nested| nested.representer_class }
9
+ }.merge(options) # TODO: options not tested.
10
+ )
25
11
  end
26
12
  end
27
13
  end
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "2.0.0.beta1"
2
+ VERSION = "2.0.0.beta2"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_dependency "representable", ">= 2.2.2"
21
- spec.add_dependency "disposable", "~> 0.1.2"
21
+ spec.add_dependency "disposable", "~> 0.1.4"
22
22
  spec.add_dependency "uber", "~> 0.0.11"
23
23
  spec.add_dependency "activemodel"
24
24
 
@@ -9,7 +9,7 @@ class CoercionTest < BaseTest
9
9
  end
10
10
 
11
11
  class Form < Reform::Form
12
- # include Coercion
12
+ feature Coercion
13
13
 
14
14
  property :released_at, :type => DateTime
15
15
 
@@ -1,37 +1,84 @@
1
1
  require 'test_helper'
2
2
  require 'reform/form/json'
3
3
 
4
- class DeserializeTest < BaseTest
5
- class AlbumContract < Reform::Form
6
- include Reform::Form::ActiveModel::FormBuilderMethods # overrides #update!, too.
4
+ class DeserializeTest < MiniTest::Spec
5
+ Song = Struct.new(:title, :album, :composer)
6
+ Album = Struct.new(:title, :artist)
7
+ Artist = Struct.new(:name)
7
8
 
8
- include Reform::Form::JSON
9
+ class JsonAlbumForm < Reform::Form
10
+ module Json
11
+ def deserialize(params)
12
+ # params = deserialize!(params) # DON'T call those hash hooks.
9
13
 
10
- property :title
11
- validates :title, :presence => true, :length => {:minimum => 3}
14
+ deserializer.new(self).
15
+ # extend(Representable::Debug).
16
+ from_json(params)
17
+ end
12
18
 
13
- property :hit do
14
- property :title
15
- validates :title, :presence => true
19
+ def deserializer
20
+ deserializer = Disposable::Twin::Schema.from(self.class,
21
+ include: [Representable::JSON],
22
+ superclass: Representable::Decorator,
23
+ representer_from: lambda { |inline| inline.representer_class },
24
+ options_from: :deserializer
25
+ )
26
+ end
16
27
  end
28
+ include Json
17
29
 
18
- property :band do # yepp, people do crazy stuff like that.
19
- validates :label, :presence => true
20
30
 
21
- property :label do
22
- property :name
23
- validates :name, :presence => true
24
- end
31
+ property :title
32
+ property :artist, populate_if_empty: Artist do
33
+ property :name
25
34
  end
26
35
  end
27
36
 
28
- let (:album) { Album.new(nil, Song.new, [Song.new, Song.new], Band.new(Label.new("Fat Wreck")) ) }
29
- subject { AlbumContract.new(album) }
37
+ let (:artist) { Artist.new("A-ha") }
38
+ it do
39
+ artist_id = artist.object_id
40
+
41
+ form = JsonAlbumForm.new(Album.new("Best Of", artist))
42
+ json = {title: "Apocalypse Soon", artist: {name: "Mute"}}.to_json
43
+
44
+ form.validate(json)
45
+
46
+ form.title.must_equal "Apocalypse Soon"
47
+ form.artist.name.must_equal "Mute"
48
+ form.artist.model.object_id.must_equal artist_id
49
+ end
50
+ end
51
+
30
52
 
31
- let (:json) { '{"hit":{"title":"Sacrifice"},"title":"Second Heat","songs":[{"title":"Heart Of A Lion"}],"band":{"label":{"name":"Fat Wreck"}}}' }
53
+ class ValidateWithBlockTest < MiniTest::Spec
54
+ Song = Struct.new(:title, :album, :composer)
55
+ Album = Struct.new(:title, :artist)
56
+ Artist = Struct.new(:name)
57
+
58
+ class AlbumForm < Reform::Form
59
+ property :title
60
+ property :artist, populate_if_empty: Artist do
61
+ property :name
62
+ end
63
+ end
32
64
 
33
65
  it do
34
- subject.validate(json)
35
- subject.band.label.name.must_equal "Fat Wreck"
66
+ album = Album.new
67
+ form = AlbumForm.new(album)
68
+ json = {title: "Apocalypse Soon", artist: {name: "Mute"}}.to_json
69
+
70
+ deserializer = Disposable::Twin::Schema.from(AlbumForm,
71
+ include: [Representable::JSON],
72
+ superclass: Representable::Decorator,
73
+ representer_from: lambda { |inline| inline.representer_class },
74
+ options_from: :deserializer
75
+ )
76
+
77
+ form.validate(json) do |params|
78
+ deserializer.new(form).from_json(params)
79
+ end.must_equal true # with block must return result, too.
80
+
81
+ form.title.must_equal "Apocalypse Soon"
82
+ form.artist.name.must_equal "Mute"
36
83
  end
37
84
  end
@@ -27,6 +27,10 @@ class FormBuilderCompatTest < BaseTest
27
27
  property :band do
28
28
  property :label do
29
29
  property :name
30
+
31
+ property :location do
32
+ property :postcode
33
+ end
30
34
  end
31
35
  end
32
36
  end
@@ -36,20 +40,21 @@ class FormBuilderCompatTest < BaseTest
36
40
  let (:form) { AlbumForm.new(OpenStruct.new(
37
41
  :artist => Artist.new(:name => "Propagandhi"),
38
42
  :songs => [song],
39
- :label => OpenStruct.new,
43
+ :label => Label.new,
40
44
 
41
- :band => Band.new(Label.new)
45
+ :band => Band.new(OpenStruct.new(location: OpenStruct.new))
42
46
  )) }
43
47
 
44
- it "respects _attributes params hash" do
48
+ it "xxxrespects _attributes params hash" do
45
49
  form.validate(
46
50
  "artist_attributes" => {"name" => "Blink 182"},
47
51
  "songs_attributes" => {"0" => {"title" => "Damnit"}},
48
- "band_attributes" => {"label_attributes" => {"name" => "Epitaph"}})
52
+ "band_attributes" => {"label_attributes" => {"name" => "Epitaph", "location_attributes" => {"postcode" => 2481}}})
49
53
 
50
54
  form.artist.name.must_equal "Blink 182"
51
55
  form.songs.first.title.must_equal "Damnit"
52
56
  form.band.label.name.must_equal "Epitaph"
57
+ form.band.label.location.postcode.must_equal 2481
53
58
  end
54
59
 
55
60
  it "allows nested collection and property to be missing" do
@@ -32,6 +32,7 @@ class FormTest < MiniTest::Spec
32
32
  end
33
33
 
34
34
  # ::schema
35
+ # TODO: refactor schema tests, this is all covered in Disposable.
35
36
  describe "::schema" do
36
37
  let (:schema) { AlbumForm.schema }
37
38
 
@@ -126,6 +126,21 @@ class ValidateWithoutConfigurationTest < MiniTest::Spec
126
126
  album.songs[1].composer.name.must_equal "Greg Graffin"
127
127
  album.artist.name.must_equal "Bad Religion"
128
128
  end
129
+
130
+ # with symbols.
131
+ it do
132
+ form.validate(
133
+ name: "Best Of",
134
+ songs: [{title: "The X-Creep"}, {title: "Trudging", composer: {name: "SNFU"}}],
135
+ artist: {name: "The Police"},
136
+ ).must_equal true
137
+
138
+ form.name.must_equal "Best Of"
139
+ form.songs[0].title.must_equal "The X-Creep"
140
+ form.songs[1].title.must_equal "Trudging"
141
+ form.songs[1].composer.name.must_equal "SNFU"
142
+ form.artist.name.must_equal "The Police"
143
+ end
129
144
  end
130
145
 
131
146
  class ValidateWithDeserializerOptionTest < MiniTest::Spec
@@ -248,7 +263,6 @@ class ValidateWithDeserializerOptionTest < MiniTest::Spec
248
263
  end
249
264
  end
250
265
 
251
-
252
266
  # # not sure if we should catch that in Reform or rather do that in disposable. this is https://github.com/apotonick/reform/pull/104
253
267
  # # describe ":populator with :empty" do
254
268
  # # let (:form) {
@@ -323,18 +337,7 @@ end
323
337
  # end
324
338
 
325
339
 
326
- # describe "with symbols" do
327
- # let (:album) { OpenStruct.new(:band => OpenStruct.new(:label => OpenStruct.new(:name => "Epitaph"))) }
328
- # subject { ErrorsTest::AlbumForm.new(album) }
329
- # let (:params) { {:band => {:label => {:name => "Stiff"}}, :title => "House Of Fun"} }
330
340
 
331
- # before {
332
- # subject.validate(params).must_equal true
333
- # }
334
-
335
- # it { subject.band.label.name.must_equal "Stiff" }
336
- # it { subject.title.must_equal "House Of Fun" }
337
- # end
338
341
 
339
342
 
340
343
  # # providing manual validator method allows accessing form's API.
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.beta1
4
+ version: 2.0.0.beta2
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-06-28 00:00:00.000000000 Z
12
+ date: 2015-06-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: representable
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 0.1.2
34
+ version: 0.1.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
- version: 0.1.2
41
+ version: 0.1.4
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: uber
44
44
  requirement: !ruby/object:Gem::Requirement