gourami 0.5.0 → 1.3.1
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/.ruby-version +1 -0
- data/README.md +62 -6
- data/Rakefile +14 -0
- data/gourami.gemspec +3 -2
- data/lib/gourami.rb +1 -0
- data/lib/gourami/attribute_name_conflict_error.rb +4 -0
- data/lib/gourami/attributes.rb +30 -3
- data/lib/gourami/coercer.rb +32 -7
- data/lib/gourami/extensions/resources.rb +22 -0
- data/lib/gourami/validation_error.rb +32 -2
- data/lib/gourami/validations.rb +17 -4
- data/lib/gourami/version.rb +1 -1
- metadata +34 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 471278c6d8c858485bdec0d124139f3ccd4251eedbad1573059dcf4519ec9b0a
|
4
|
+
data.tar.gz: 2e62de42a3eb36e05cd247bed62ccb7f7bfecb796318a1b0c5dfeb79ce6b28bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09d6304054c99cbf3587005dfc38c8fef568dff2339cfc1ae41642bacbf4c80da1a91c54bc435b90253ac01d7c72927f516b945838db698d33df7250bb686499'
|
7
|
+
data.tar.gz: e33e55074af37d7776329feb8a491687ab43dea237d5ce96cd4dd9ff1d80f6a580b43b6015021c69a9444d48f788bcd1bd16c512f07da4f6377f3a19d0682ea8
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.3
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Gourami
|
2
2
|
|
3
|
+
[](https://app.codeship.com/projects/320673)
|
4
|
+
|
3
5
|
Keep your Routes, Controllers and Models thin with Plain Old Ruby Objects (PORO).
|
4
6
|
|
5
7
|
## Installation
|
@@ -12,7 +14,7 @@ gem 'gourami'
|
|
12
14
|
|
13
15
|
And then execute:
|
14
16
|
|
15
|
-
$ bundle
|
17
|
+
$ bundle install
|
16
18
|
|
17
19
|
Or install it yourself as:
|
18
20
|
|
@@ -20,10 +22,10 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
## Usage
|
22
24
|
|
23
|
-
### A Typical Gourami::Form will
|
25
|
+
### A Typical `Gourami::Form` will
|
24
26
|
|
25
|
-
- Define
|
26
|
-
- Validate
|
27
|
+
- Define attributes (inputs & outputs)
|
28
|
+
- Validate input
|
27
29
|
- Perform an action
|
28
30
|
|
29
31
|
```ruby
|
@@ -173,6 +175,56 @@ class UpdateFishBowl < CreateFishBowl
|
|
173
175
|
end
|
174
176
|
```
|
175
177
|
|
178
|
+
#### Configure default attribute options
|
179
|
+
|
180
|
+
The following examples will result in all `:string` attributes getting the options `:strip` and `:upcase` set to `true`.
|
181
|
+
|
182
|
+
Set global defaults:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
Gourami::Form.set_default_attribute_options(:string, upcase: true)
|
186
|
+
|
187
|
+
# Make sure to define CreateFishBowl and other forms AFTER setting default options.
|
188
|
+
class CreateFishBowl < Gourami::Form
|
189
|
+
attribute(:name, type: :string)
|
190
|
+
end
|
191
|
+
|
192
|
+
form = CreateFishBowl.new(name: "Snake Gyllenhaal")
|
193
|
+
form.name # => "SNAKE GYLLENHAAL"
|
194
|
+
```
|
195
|
+
|
196
|
+
Instead of global defaults, you can also apply defaults to certain form classes.
|
197
|
+
|
198
|
+
Just as `attributes` are inherited by subclasses, so are `default_attribute_options`.
|
199
|
+
|
200
|
+
Set local defaults:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
class ScreamingForm < Gourami::Form
|
204
|
+
set_default_attribute_options(:string, upcase: true)
|
205
|
+
end
|
206
|
+
|
207
|
+
class CreateScreamingFish < ScreamingForm
|
208
|
+
attribute(:name, type: :string)
|
209
|
+
end
|
210
|
+
|
211
|
+
class UpdateScreamingFish < CreateScreamingFish; end
|
212
|
+
|
213
|
+
create_form = CreateScreamingFish.new(name: "Snake Gyllenhaal")
|
214
|
+
create_form.name # => "SNAKE GYLLENHAAL"
|
215
|
+
|
216
|
+
update_form = UpdateScreamingFish.new(name: "Snake Gyllenhaal")
|
217
|
+
update_form.name # => "SNAKE GYLLENHAAL"
|
218
|
+
|
219
|
+
# Other Gourami::Forms are unaffected
|
220
|
+
class RegularForm < Gourami::Form
|
221
|
+
attribute(:name, type: :string)
|
222
|
+
end
|
223
|
+
|
224
|
+
regular_form = RegularForm.new(name: "Snake Gyllenhaal")
|
225
|
+
regular_form.name # => "Snake Gyllenhaal"
|
226
|
+
```
|
227
|
+
|
176
228
|
#### Extensions / Plugins
|
177
229
|
|
178
230
|
##### Gourami::Extensions::Changes
|
@@ -250,9 +302,13 @@ end
|
|
250
302
|
|
251
303
|
## Development
|
252
304
|
|
253
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
305
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests, or `rake test:watch` to automatically rerun the tests when you make code changes. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
306
|
+
|
307
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
308
|
+
|
309
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
254
310
|
|
255
|
-
To
|
311
|
+
To add another gem owner to gourami gem `gem owner --add john.smith@example.com gourami`
|
256
312
|
|
257
313
|
## Contributing
|
258
314
|
|
data/Rakefile
CHANGED
@@ -8,4 +8,18 @@ Rake::TestTask.new(:test) do |t|
|
|
8
8
|
end
|
9
9
|
|
10
10
|
task :spec => :test
|
11
|
+
namespace :test do
|
12
|
+
task :watch do |t, args|
|
13
|
+
require "filewatcher"
|
14
|
+
|
15
|
+
watcher = Filewatcher.new(["spec/", "lib/"], :every => true, :spinner => true, :immediate => true)
|
16
|
+
watcher.watch do |filename, event|
|
17
|
+
begin
|
18
|
+
Rake::Task[:test].execute(args)
|
19
|
+
rescue StandardError => error
|
20
|
+
puts "Error: #{error.message}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
11
25
|
task :default => :test
|
data/gourami.gemspec
CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
+
spec.add_development_dependency "activesupport", ">= 5.1.7"
|
25
|
+
spec.add_development_dependency "filewatcher", "~> 1.1.0"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
24
27
|
spec.add_development_dependency "pry", "~>0.10"
|
25
|
-
spec.add_development_dependency "bundler", "~> 1.13"
|
26
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
28
29
|
end
|
data/lib/gourami.rb
CHANGED
data/lib/gourami/attributes.rb
CHANGED
@@ -2,12 +2,14 @@ module Gourami
|
|
2
2
|
module Attributes
|
3
3
|
|
4
4
|
module ClassMethods
|
5
|
+
|
5
6
|
# Copy parent attributes to inheriting class.
|
6
7
|
#
|
7
8
|
# @param klass [Class]
|
8
9
|
def inherited(klass)
|
9
10
|
super(klass)
|
10
11
|
klass.instance_variable_set(:@attributes, attributes.dup)
|
12
|
+
klass.instance_variable_set(:@default_attribute_options, default_attribute_options.dup)
|
11
13
|
end
|
12
14
|
|
13
15
|
# Define an attribute for the form.
|
@@ -20,14 +22,21 @@ module Gourami
|
|
20
22
|
# @block default_block
|
21
23
|
# If provided, the block will be applied to options as the :default
|
22
24
|
def attribute(name, options = {}, &default_block)
|
25
|
+
base = self
|
23
26
|
options = options.dup
|
24
27
|
options[:default] = default_block if block_given?
|
25
28
|
|
29
|
+
options_with_defaults = merge_default_attribute_options(options)
|
30
|
+
|
26
31
|
mixin = Module.new do |mixin|
|
27
|
-
unless
|
32
|
+
unless options_with_defaults[:skip_reader]
|
33
|
+
if !base.attributes.key?(name) && base.instance_methods.include?(name) && !options_with_defaults[:override_reader]
|
34
|
+
raise AttributeNameConflictError, "#{name} is already a method. To use the existing method, use `:skip_reader => true` option. To override the existing method, use `:override_reader => true` option."
|
35
|
+
end
|
36
|
+
|
28
37
|
mixin.send(:define_method, :"#{name}") do
|
29
38
|
value = instance_variable_get(:"@#{name}")
|
30
|
-
default =
|
39
|
+
default = options_with_defaults[:default]
|
31
40
|
|
32
41
|
if value.nil? && default
|
33
42
|
default.respond_to?(:call) ? instance_exec(&default) : default
|
@@ -45,7 +54,7 @@ module Gourami
|
|
45
54
|
|
46
55
|
# Define internal setter.
|
47
56
|
mixin.send(:define_method, :"_#{name}=") do |value|
|
48
|
-
instance_variable_set(:"@#{name}", setter_filter(name, value, options))
|
57
|
+
instance_variable_set(:"@#{name}", setter_filter(name, value, self.class.merge_default_attribute_options(options)))
|
49
58
|
end
|
50
59
|
mixin.send(:private, :"_#{name}=")
|
51
60
|
|
@@ -84,6 +93,24 @@ module Gourami
|
|
84
93
|
def attributes
|
85
94
|
@attributes ||= {}
|
86
95
|
end
|
96
|
+
|
97
|
+
# Useful if you want, for example, all type: :string attributes to use
|
98
|
+
# strip: true to remove whitespace padding.
|
99
|
+
def set_default_attribute_options(attr_type, options)
|
100
|
+
default_attribute_options[attr_type] = options
|
101
|
+
end
|
102
|
+
|
103
|
+
def default_attribute_options
|
104
|
+
@default_attribute_options ||= {}
|
105
|
+
end
|
106
|
+
|
107
|
+
def merge_default_attribute_options(options)
|
108
|
+
if options[:type]
|
109
|
+
default_attribute_options.fetch(options[:type], {}).merge(options)
|
110
|
+
else
|
111
|
+
options
|
112
|
+
end
|
113
|
+
end
|
87
114
|
end
|
88
115
|
|
89
116
|
# Extend ClassMethods into including class.
|
data/lib/gourami/coercer.rb
CHANGED
@@ -11,8 +11,7 @@ module Gourami
|
|
11
11
|
# @return [*]
|
12
12
|
def setter_filter(attribute_name, value, options)
|
13
13
|
type = options[:type]
|
14
|
-
|
15
|
-
value = send(coercer_method_name, value, options) if type
|
14
|
+
value = send(:"coerce_#{type}", value, options) if type
|
16
15
|
|
17
16
|
super(attribute_name, value, options)
|
18
17
|
end
|
@@ -34,6 +33,9 @@ module Gourami
|
|
34
33
|
end
|
35
34
|
|
36
35
|
value = value.to_s.dup.force_encoding(Encoding::UTF_8)
|
36
|
+
|
37
|
+
# TODO: Instead of providing unconfigurable defaults like this, use
|
38
|
+
# set_default_attribute_options at the gem level or consumer level.
|
37
39
|
value.strip! if options.fetch(:strip, true)
|
38
40
|
value.upcase! if options.fetch(:upcase, false)
|
39
41
|
|
@@ -85,6 +87,9 @@ module Gourami
|
|
85
87
|
element_type_options = {}
|
86
88
|
end
|
87
89
|
|
90
|
+
element_type_options[:type] = element_type
|
91
|
+
element_type_options = self.class.merge_default_attribute_options(element_type_options) if self.class.respond_to?(:merge_default_attribute_options)
|
92
|
+
|
88
93
|
coercer_method_name = :"coerce_#{element_type}"
|
89
94
|
|
90
95
|
value.map do |array_element|
|
@@ -120,21 +125,41 @@ module Gourami
|
|
120
125
|
# The type of the hash keys to coerce, no coersion if value is nil.
|
121
126
|
# @option options :value_type [Symbol, Callable] (nil)
|
122
127
|
# The type of the hash values to coerce, no coersion if value is nil.
|
128
|
+
# @option options :indifferent_access [Boolean] (false)
|
129
|
+
# When true, the resulting Hash will be an ActiveSupport::HashWithIndifferentAccess
|
123
130
|
#
|
124
|
-
# @return [Hash]
|
131
|
+
# @return [Hash, ActiveSupport::HashWithIndifferentAccess]
|
125
132
|
# The coerced Hash.
|
126
133
|
def coerce_hash(value, options = {})
|
134
|
+
return if options[:allow_nil] && value.nil?
|
135
|
+
|
127
136
|
hash_key_type = options[:key_type]
|
128
137
|
hash_value_type = options[:value_type]
|
129
138
|
|
130
|
-
|
139
|
+
hash_class = options[:indifferent_access] ? ActiveSupport::HashWithIndifferentAccess : Hash
|
140
|
+
hash = hash_class.new
|
141
|
+
|
142
|
+
return hash unless value.is_a?(Hash) || (defined?(Sequel::Postgres::JSONHash) && value.is_a?(Sequel::Postgres::JSONHash))
|
131
143
|
|
132
|
-
value.each_with_object(
|
144
|
+
value.each_with_object(hash) do |(key, value), coerced_hash|
|
133
145
|
key_type = hash_key_type.respond_to?(:call) ? hash_key_type.call(key, value) : hash_key_type
|
134
|
-
key = send("coerce_#{key_type}", key) if key_type
|
146
|
+
key = send(:"coerce_#{key_type}", key) if key_type
|
135
147
|
|
136
148
|
value_type = hash_value_type.respond_to?(:call) ? hash_value_type.call(key, value) : hash_value_type
|
137
|
-
|
149
|
+
|
150
|
+
# TODO: Refactor shared logic here and coerce_array to a method like `type, options = resolve_coercer_type_and_options`
|
151
|
+
if value_type.is_a?(Hash)
|
152
|
+
value_type_options = value_type
|
153
|
+
value_type = value_type[:type]
|
154
|
+
else
|
155
|
+
value_type_options = {}
|
156
|
+
end
|
157
|
+
|
158
|
+
value_type_options[:type] = value_type
|
159
|
+
value_type_options = self.class.merge_default_attribute_options(value_type_options) if self.class.respond_to?(:merge_default_attribute_options)
|
160
|
+
|
161
|
+
value = send(:"coerce_#{value_type}", value, value_type_options) if value_type
|
162
|
+
|
138
163
|
coerced_hash[key] = value
|
139
164
|
end
|
140
165
|
end
|
@@ -91,6 +91,28 @@ module Gourami
|
|
91
91
|
resource_errors.values.flat_map(&:values).map(&:values).flatten.any?
|
92
92
|
end
|
93
93
|
|
94
|
+
# Replace the existing resource errors with the provided errors Hash.
|
95
|
+
#
|
96
|
+
# @param new_resource_errors [Hash<Symbol, Hash<Symbol, Hash<Symbol, Array>>>]
|
97
|
+
#
|
98
|
+
# @return [Hash<Symbol, Hash<Symbol, Hash<Symbol, Array>>>]
|
99
|
+
def clear_and_set_resource_errors(new_resource_errors)
|
100
|
+
new_resource_errors = new_resource_errors.dup
|
101
|
+
resource_errors.clear
|
102
|
+
resource_errors.merge!(new_resource_errors)
|
103
|
+
|
104
|
+
resource_errors
|
105
|
+
end
|
106
|
+
|
107
|
+
def handle_validation_error(error)
|
108
|
+
super(error)
|
109
|
+
clear_and_set_resource_errors(error.resource_errors) unless error.resource_errors.nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
def raise_validate_errors
|
113
|
+
raise ValidationError.new(errors, resource_errors)
|
114
|
+
end
|
115
|
+
|
94
116
|
end
|
95
117
|
end
|
96
118
|
end
|
@@ -9,20 +9,39 @@ module Gourami
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.stringify_resource_errors(resource_errors)
|
13
|
+
[].tap do |array|
|
14
|
+
resource_errors.each do |resource_namespace, resource_namespace_errors|
|
15
|
+
resource_namespace_errors.each do |resource_uid, resource_uid_errors|
|
16
|
+
resource_uid_errors.each do |attribute_name, error|
|
17
|
+
array.push("#{resource_namespace}:#{resource_uid}:#{attribute_name}: #{error}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
12
24
|
# !@attribute [r] errors
|
13
25
|
# @return [Hash<Symbol, Array>]
|
14
26
|
attr_reader :errors
|
15
27
|
|
28
|
+
# !@attribute [r] resource_errors
|
29
|
+
# @return [Hash<Symbol, Hash<Symbol, Hash<Symbol, Array>>>]
|
30
|
+
attr_reader :resource_errors
|
31
|
+
|
16
32
|
# Initialize the Gourami::ValidationError.
|
17
33
|
#
|
18
34
|
# @param errors [Hash<Symbol, Array>]
|
19
|
-
|
35
|
+
# @param resource_errors [Hash<Symbol, Hash<Symbol, Hash<Symbol, Array>>>]
|
36
|
+
def initialize(errors, resource_errors = {})
|
37
|
+
@resource_errors = resource_errors
|
20
38
|
@errors = errors
|
39
|
+
|
21
40
|
super(message)
|
22
41
|
end
|
23
42
|
|
24
43
|
def message
|
25
|
-
@message ||=
|
44
|
+
@message ||= stringify_all_errors
|
26
45
|
end
|
27
46
|
|
28
47
|
private
|
@@ -31,5 +50,16 @@ module Gourami
|
|
31
50
|
ValidationError.stringify_errors(errors)
|
32
51
|
end
|
33
52
|
|
53
|
+
def stringify_resource_errors
|
54
|
+
ValidationError.stringify_resource_errors(resource_errors)
|
55
|
+
end
|
56
|
+
|
57
|
+
def stringify_all_errors
|
58
|
+
messages = []
|
59
|
+
messages << "Validation failed with errors: #{stringify_errors.join("\n")}" unless errors.nil? || errors.empty?
|
60
|
+
messages << "Validation failed with resource errors: #{stringify_resource_errors.join("\n")}" unless resource_errors.nil? || resource_errors.empty?
|
61
|
+
messages.join("\n")
|
62
|
+
end
|
63
|
+
|
34
64
|
end
|
35
65
|
end
|
data/lib/gourami/validations.rb
CHANGED
@@ -15,11 +15,16 @@ module Gourami
|
|
15
15
|
# @raise [Gourami::ValidationError]
|
16
16
|
def perform!
|
17
17
|
if valid?
|
18
|
-
|
18
|
+
begin
|
19
|
+
returned = perform
|
20
|
+
rescue Gourami::ValidationError => error
|
21
|
+
handle_validation_error(error)
|
22
|
+
raise
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
if any_errors?
|
22
|
-
|
27
|
+
raise_validate_errors
|
23
28
|
end
|
24
29
|
|
25
30
|
returned
|
@@ -46,9 +51,9 @@ module Gourami
|
|
46
51
|
|
47
52
|
# Replace the existing errors with the provided errors Hash.
|
48
53
|
#
|
49
|
-
# @param new_errors
|
54
|
+
# @param new_errors Hash<Symbol, Array>
|
50
55
|
#
|
51
|
-
# @return
|
56
|
+
# @return Hash<Symbol, Array>
|
52
57
|
def clear_and_set_errors(new_errors)
|
53
58
|
new_errors = new_errors.dup
|
54
59
|
errors.clear
|
@@ -57,6 +62,14 @@ module Gourami
|
|
57
62
|
errors
|
58
63
|
end
|
59
64
|
|
65
|
+
def raise_validate_errors
|
66
|
+
raise ValidationError.new(errors)
|
67
|
+
end
|
68
|
+
|
69
|
+
def handle_validation_error(error)
|
70
|
+
clear_and_set_errors(error.errors) unless error.errors.nil?
|
71
|
+
end
|
72
|
+
|
60
73
|
# Return true if there given attribute has any errors.
|
61
74
|
def attribute_has_errors?(attribute_name)
|
62
75
|
errors[attribute_name.to_sym].any?
|
data/lib/gourami/version.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gourami
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TSMMark
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.7
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.1.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: filewatcher
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
33
|
+
version: 1.1.0
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
40
|
+
version: 1.1.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
42
|
+
name: minitest
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '5.0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '5.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: pry
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '10
|
61
|
+
version: '0.10'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '10
|
68
|
+
version: '0.10'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '10.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '10.0'
|
69
83
|
description: Create Plain Old Ruby Objects that take attributes, validate them, and
|
70
84
|
perform an action.
|
71
85
|
email:
|
@@ -75,6 +89,7 @@ extensions: []
|
|
75
89
|
extra_rdoc_files: []
|
76
90
|
files:
|
77
91
|
- ".gitignore"
|
92
|
+
- ".ruby-version"
|
78
93
|
- ".travis.yml"
|
79
94
|
- CODE_OF_CONDUCT.md
|
80
95
|
- Gemfile
|
@@ -85,6 +100,7 @@ files:
|
|
85
100
|
- bin/setup
|
86
101
|
- gourami.gemspec
|
87
102
|
- lib/gourami.rb
|
103
|
+
- lib/gourami/attribute_name_conflict_error.rb
|
88
104
|
- lib/gourami/attributes.rb
|
89
105
|
- lib/gourami/coercer.rb
|
90
106
|
- lib/gourami/configuration_error.rb
|
@@ -103,7 +119,7 @@ homepage: http://github.com/Vydia/gourami
|
|
103
119
|
licenses:
|
104
120
|
- MIT
|
105
121
|
metadata: {}
|
106
|
-
post_install_message:
|
122
|
+
post_install_message:
|
107
123
|
rdoc_options: []
|
108
124
|
require_paths:
|
109
125
|
- lib
|
@@ -118,9 +134,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
134
|
- !ruby/object:Gem::Version
|
119
135
|
version: '0'
|
120
136
|
requirements: []
|
121
|
-
|
122
|
-
|
123
|
-
signing_key:
|
137
|
+
rubygems_version: 3.0.4
|
138
|
+
signing_key:
|
124
139
|
specification_version: 4
|
125
140
|
summary: Keep your Routes, Controllers and Models thin.
|
126
141
|
test_files: []
|