scrivener 0.3.0 → 1.1.1

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
- SHA1:
3
- metadata.gz: dc1f71859949ac9d78b3bc589d6d04ec70531240
4
- data.tar.gz: 5bbd3d104350d6472cd03da0f18c1d90b6120dea
2
+ SHA256:
3
+ metadata.gz: e94b74d62fa478e7e64a92078e84e8734897c3b2e5e7e7de2c158185aab79e34
4
+ data.tar.gz: c25c6bbb36c7c7d55ec6edbc037154dae6af10fd07210f790d17338148458020
5
5
  SHA512:
6
- metadata.gz: dd5c732af472a97cfdd34d0091fa9eab509d9121d57369b1197cd259e7f1bdb8a02c7fdccf7746cf753819b838a00c8b456d1e856192f1f80fc228ad2b2ce60f
7
- data.tar.gz: 2117ae9707e937dfa06d4ae54b99b8a299dcb6ead0aca9ca14a354e05fd570706b065bb344a5896cf9aad9b1346d2bd7f85bfad8aca33008e8516e6547ad2dd9
6
+ metadata.gz: 2c908c3f6be324ea81a909ec081669e6615b1810c692c3e1ef5cb95342188fcb133fdb5c69ff6312879ae37b26361b5abdf01382974e1560c257fffb662e28b2
7
+ data.tar.gz: acfb6f2cac8005c9d13e0c767cdec34258b85d6f29d59a5138e885a298e109ee6d56aea724e7b4cb1fc536e7299801e2c69fd11a0f192f1f458d5cdc4ff331e3
data/.gems ADDED
@@ -0,0 +1 @@
1
+ cutest -v 1.2.2
@@ -0,0 +1 @@
1
+ /pkg
@@ -0,0 +1,41 @@
1
+ ## 1.1.1
2
+
3
+ * Avoid warning when forwarding arguments to #validate.
4
+
5
+ ## 1.1.0
6
+
7
+ * Allow passing arguments to Scrivener#validate.
8
+
9
+ ## 1.0.0
10
+
11
+ * Extra attributes are ignored.
12
+
13
+ ```ruby
14
+ # Before:
15
+
16
+ publish = Publish.new(status: "published", title: "foo")
17
+ publis.attributes # => { :status => "published" }
18
+ # => NoMethodError: undefined method `title=' for #<Publish...>
19
+
20
+ # Now:
21
+
22
+ # Extra fields are discarded
23
+ publish = Publish.new(status: "published", title: "foo")
24
+ publish.attributes # => { :status => "published" }
25
+ ```
26
+
27
+ ## 0.4.1
28
+
29
+ * Fix creation of symbols for extra attributes.
30
+
31
+ ## 0.4.0
32
+
33
+ * Fix `assert_email` and `assert_url` to support longer tld's.
34
+
35
+ ## 0.3.0
36
+
37
+ * Add support for negative numbers.
38
+
39
+ ## 0.2.0
40
+
41
+ * Add `assert_equal` validation.
@@ -0,0 +1,19 @@
1
+ This code tries to solve a particular problem with a very simple
2
+ implementation. We try to keep the code to a minimum while making
3
+ it as clear as possible. The design is very likely finished, and
4
+ if some feature is missing it is possible that it was left out on
5
+ purpose. That said, new usage patterns may arise, and when that
6
+ happens we are ready to adapt if necessary.
7
+
8
+ A good first step for contributing is to meet us on IRC and discuss
9
+ ideas. We spend a lot of time on #lesscode at freenode, always ready
10
+ to talk about code and simplicity. If connecting to IRC is not an
11
+ option, you can create an issue explaining the proposed change and
12
+ a use case. We pay a lot of attention to use cases, because our
13
+ goal is to keep the code base simple. Usually the result of a
14
+ conversation is the creation of a different tool.
15
+
16
+ Please don't start the conversation with a pull request. The code
17
+ should come at last, and even though it may help to convey an idea,
18
+ more often than not it draws the attention to a particular
19
+ implementation.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Michel Martens
1
+ Copyright (c) 2011-2015 Michel Martens
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -6,81 +6,18 @@ Validation frontend for models.
6
6
  Description
7
7
  -----------
8
8
 
9
- Scrivener removes the validation responsibility from models and acts as a
10
- filter for whitelisted attributes.
11
-
12
- A model may expose different APIs to satisfy different purposes. For example,
13
- the set of validations for a User in a Sign up process may not be the same
14
- as the one exposed to an Admin when editing a user profile. While you want
15
- the User to provide an email, a password and a password confirmation, you
16
- probably don't want the admin to mess with those attributes at all.
17
-
18
- In a wizard, different model states ask for different validations, and a single
19
- set of validations for the whole process is not the best solution.
20
-
21
- Scrivener is Bureaucrat's little brother. It draws all the inspiration from it
22
- and its features are a subset of Bureaucrat's. For a more robust and tested
23
- solution, please [check it](https://github.com/tizoc/bureaucrat).
24
-
25
- This library exists to satify the need of extracting Ohm's validations for
26
- reuse in other scenarios.
9
+ Scrivener removes the validation responsibility from models and
10
+ acts as a filter for whitelisted attributes. Read about the
11
+ [motivation](#motivation) to understand why this separation of
12
+ concerns is important.
27
13
 
28
14
  Usage
29
15
  -----
30
16
 
31
- Using Scrivener feels very natural no matter what underlying model you are
32
- using. As it provides its own validation and whitelisting features, you can
33
- choose to ignore the ones that come bundled with ORMs.
34
-
35
- This short example illustrates how to move the validation and whitelisting
36
- responsibilities away from the model and into Scrivener:
17
+ A very basic example would be creating a blog post:
37
18
 
38
19
  ```ruby
39
- # We use Sequel::Model in this example, but it applies to other ORMs such
40
- # as Ohm or ActiveRecord.
41
- class Article < Sequel::Model
42
-
43
- # Whitelist for mass assigned attributes.
44
- set_allowed_columns :title, :body, :state
45
-
46
- # Validations for all contexts.
47
- def validate
48
- validates_presence :title
49
- validates_presence :body
50
- validates_presence :state
51
- end
52
- end
53
-
54
- title = "Bartleby, the Scrivener"
55
- body = "I am a rather elderly man..."
56
-
57
- # When using the model...
58
- article = Article.new(title: title, body: body)
59
-
60
- article.valid? #=> false
61
- article.errors[:state] #=> [:not_present]
62
- ```
63
-
64
- Of course, what you would do instead is declare `:title` and `:body` as allowed
65
- columns, then assign `:state` using the attribute accessor. The reason for this
66
- example is to show how you need to work around the fact that there's a single
67
- declaration for allowed columns and validations, which in many cases is a great
68
- feature and in others is a minor obstacle.
69
-
70
- Now see what happens with Scrivener:
71
-
72
- ```ruby
73
- # Now the model has no validations or whitelists. It may still have schema
74
- # constraints, which is a good practice to enforce data integrity.
75
- class Article < Sequel::Model
76
- end
77
-
78
- # The attribute accessors are the only fields that will be set. If more
79
- # fields are sent when using mass assignment, a NoMethodError exception is
80
- # raised.
81
- #
82
- # Note how in this example we don't accept the status attribute.
83
- class Edit < Scrivener
20
+ class CreateBlogPost < Scrivener
84
21
  attr_accessor :title
85
22
  attr_accessor :body
86
23
 
@@ -89,44 +26,42 @@ class Edit < Scrivener
89
26
  assert_present :body
90
27
  end
91
28
  end
29
+ ```
92
30
 
93
- edit = Edit.new(title: title, body: body)
94
- edit.valid? #=> true
95
-
96
- article = Article.new(edit.attributes)
97
- article.save
98
-
99
- # And now we only ask for the status.
100
- class Publish < Scrivener
101
- attr_accessor :status
31
+ In order to use it, you have to create an instance of `CreateBlogPost`
32
+ by passing a hash with the attributes `title` and `body` and their
33
+ corresponding values:
102
34
 
103
- def validate
104
- assert_format :status, /^(published|draft)$/
105
- end
106
- end
35
+ ```ruby
36
+ params = {
37
+ title: "Bartleby",
38
+ body: "I am a rather elderly man..."
39
+ }
107
40
 
108
- publish = Publish.new(status: "published")
109
- publish.valid? #=> true
41
+ filter = CreateBlogPost.new(params)
42
+ ```
110
43
 
111
- article.update_attributes(publish.attributes)
44
+ Now you can run the validations by calling `filter.valid?`, and you
45
+ can retrieve the attributes by calling `filter.attributes`. If the
46
+ validation fails, a hash of attributes and error codes will be
47
+ available by calling `filter.errors`. For example:
112
48
 
113
- # If we try to change other fields...
114
- publish = Publish.new(status: "published", title: "foo")
115
- #=> NoMethodError: undefined method `title=' for #<Publish...>
49
+ ```ruby
50
+ if filter.valid?
51
+ puts filter.attributes
52
+ else
53
+ puts filter.errors
54
+ end
116
55
  ```
117
56
 
118
- It's important to note that using Scrivener implies a greater risk than using
119
- the model validations. Having a central repository of mass assignable
120
- attributes and validations is more secure in most scenarios.
57
+ For now, we are just printing the attributes and the list of errors,
58
+ but often you will use the attributes to create an instance of a
59
+ model, and you will display the error messages in a view.
121
60
 
122
- Slices
123
- ------
124
-
125
- If you don't need all the attributes after the filtering is done,
126
- you can fetch just the ones you need. For example:
61
+ Let's consider the case of creating a new user:
127
62
 
128
63
  ```ruby
129
- class SignUp < Scrivener
64
+ class CreateUser < Scrivener
130
65
  attr_accessor :email
131
66
  attr_accessor :password
132
67
  attr_accessor :password_confirmation
@@ -135,41 +70,79 @@ class SignUp < Scrivener
135
70
  assert_email :email
136
71
 
137
72
  if assert_present :password
138
- assert_equal :password, :password_confirmation
73
+ assert_equal :password, password_confirmation
139
74
  end
140
75
  end
141
-
142
- def assert_equal(f1, f2)
143
- assert send(f1) == send(f2), [f1, f2, :not_equal]
144
- end
145
76
  end
77
+ ```
78
+
79
+ The filter looks very similar, but as you can see the validations
80
+ return booleans, thus they can be nested. In this example, we don't
81
+ want to bother asserting if the password and the password confirmation
82
+ are equal if the password was not provided.
83
+
84
+ Let's instantiate the filter:
146
85
 
147
- filter = SignUp.new(email: "info@example.com",
148
- password: "monkey",
149
- password_confirmation: "monkey")
86
+ ```ruby
87
+ params = {
88
+ email: "info@example.com",
89
+ password: "monkey",
90
+ password_confirmation: "monkey"
91
+ }
92
+
93
+ filter = CreateUser.new(params)
94
+ ```
150
95
 
96
+ If the validation succeeds, we only need email and password to
97
+ create a new user, and we can discard the password_confirmation.
98
+ The `filter.slice` method receives a list of attributes and returns
99
+ the attributes hash with any other attributes removed. In this
100
+ example, the hash returned by `filter.slice` will contain only the
101
+ `email` and `password` fields:
151
102
 
152
- # If the validation succeeds, we only need email and password to
153
- # create a new user, and we can discard the password_confirmation.
103
+ ```ruby
154
104
  if filter.valid?
155
105
  User.create(filter.slice(:email, :password))
156
106
  end
157
107
  ```
158
108
 
159
- By calling `slice` with a list of attributes, you get a hash with only
160
- those key/value pairs.
109
+ Sometimes we might want to use parameters from the outside for validation,
110
+ but don't want the validator to treat them as attributes. In that case we
111
+ can pass arguments to `#valid?`, and they will be forwarded to `#validate`.
112
+
113
+ ```ruby
114
+ class CreateComment < Scrivener
115
+ attr_accessor :content
116
+ attr_accessor :article_id
117
+
118
+ def validate(available_articles:)
119
+ assert_present :content
120
+ assert_member :article_id, available_articles.map(&:id)
121
+ end
122
+ end
123
+ ```
124
+
125
+ ```ruby
126
+ params = {
127
+ content: "this is a comment",
128
+ article_id: 57,
129
+ }
130
+
131
+ filter = CreateComment.new(params)
132
+
133
+ filter.valid?(available_articles: user.articles)
134
+ ```
161
135
 
162
136
  Assertions
163
137
  -----------
164
138
 
165
- Scrivener ships with some basic assertions. The following is a brief description
166
- for each of them:
139
+ Scrivener ships with some basic assertions.
167
140
 
168
141
  ### assert
169
142
 
170
143
  The `assert` method is used by all the other assertions. It pushes the
171
144
  second parameter to the list of errors if the first parameter evaluates
172
- to false.
145
+ to `false` or `nil`.
173
146
 
174
147
  ``` ruby
175
148
  def assert(value, error)
@@ -177,10 +150,23 @@ def assert(value, error)
177
150
  end
178
151
  ```
179
152
 
153
+ New assertions can be built upon existing ones. For example, let's
154
+ define an assertion for positive numbers:
155
+
156
+ ```ruby
157
+ def assert_positive(att, error = [att, :not_positive])
158
+ assert(send(att) > 0, error)
159
+ end
160
+ ```
161
+
162
+ This assertion calls `assert` and passes both the result of evaluating
163
+ `send(att) > 0` and the array with the attribute and the error code.
164
+ All assertions respect this API.
165
+
180
166
  ### assert_present
181
167
 
182
- Checks that the given field is not nil or empty. The error code for this
183
- assertion is `:not_present`.
168
+ Checks that the given field is not nil or empty. The error code for
169
+ this assertion is `:not_present`.
184
170
 
185
171
  ### assert_equal
186
172
 
@@ -245,6 +231,36 @@ of the word. Valid numbers are: 0.1, .1, 1, 1.1, 3.14159, etc.
245
231
 
246
232
  The error code for this assertion is `:not_decimal`.
247
233
 
234
+ Motivation
235
+ ----------
236
+
237
+ A model may expose different APIs to satisfy different purposes.
238
+ For example, the set of validations for a User in a sign up process
239
+ may not be the same as the one exposed to an Admin when editing a
240
+ user profile. While you want the User to provide an email, a password
241
+ and a password confirmation, you probably don't want the admin to
242
+ mess with those attributes at all.
243
+
244
+ In a wizard, different model states ask for different validations,
245
+ and a single set of validations for the whole process is not the
246
+ best solution.
247
+
248
+ This library exists to satisfy the need for extracting
249
+ [Ohm](http://ohm.keyvalue.org)'s validations for reuse in other
250
+ scenarios.
251
+
252
+ Using Scrivener feels very natural no matter what underlying model
253
+ you are using. As it provides its own validation and whitelisting
254
+ features, you can choose to ignore those that come bundled with
255
+ ORMs.
256
+
257
+ See also
258
+ --------
259
+
260
+ Scrivener is [Bureaucrat](https://github.com/tizoc/bureaucrat)'s
261
+ little brother. It draws all the inspiration from it and its features
262
+ are a subset of Bureaucrat's.
263
+
248
264
  Installation
249
265
  ------------
250
266
 
@@ -1,12 +1,12 @@
1
1
  require_relative "scrivener/validations"
2
2
 
3
3
  class Scrivener
4
- VERSION = "0.3.0"
4
+ VERSION = "1.1.1"
5
5
 
6
6
  include Validations
7
7
 
8
8
  # Initialize with a hash of attributes and values.
9
- # If extra attributes are sent, a NoMethodError exception will be raised.
9
+ # Extra attributes are discarded.
10
10
  #
11
11
  # @example
12
12
  #
@@ -36,17 +36,25 @@ class Scrivener
36
36
  # post.save
37
37
  def initialize(atts)
38
38
  atts.each do |key, val|
39
- send(:"#{key}=", val)
39
+ accessor = "#{key}="
40
+
41
+ if respond_to?(accessor)
42
+ send(accessor, val)
43
+ end
44
+ end
45
+ end
46
+
47
+ def _accessors
48
+ public_methods(false).select do |name|
49
+ name[-1] == "="
40
50
  end
41
51
  end
42
52
 
43
53
  # Return hash of attributes and values.
44
54
  def attributes
45
55
  Hash.new.tap do |atts|
46
- instance_variables.each do |ivar|
47
- next if ivar == :@errors
48
-
49
- att = ivar[1..-1].to_sym
56
+ _accessors.each do |accessor|
57
+ att = accessor[0..-2].to_sym
50
58
  atts[att] = send(att)
51
59
  end
52
60
  end
@@ -67,14 +67,14 @@ class Scrivener
67
67
  # end
68
68
  # end
69
69
  #
70
- def valid?
70
+ def valid?(*args, **kargs)
71
71
  errors.clear
72
- validate
72
+ validate(*args, **kargs)
73
73
  errors.empty?
74
74
  end
75
75
 
76
76
  # Base validate implementation. Override this method in subclasses.
77
- def validate
77
+ def validate(*args, **kargs)
78
78
  end
79
79
 
80
80
  # Hash of errors for each attribute in this model.
@@ -121,7 +121,7 @@ class Scrivener
121
121
  end
122
122
  end
123
123
 
124
- URL = /\A(http|https):\/\/([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}|(2
124
+ URL = /\A(http|https):\/\/([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,12}|(2
125
125
  5[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}
126
126
  |localhost)(:[0-9]{1,5})?(\/.*)?\z/ix
127
127
 
@@ -134,7 +134,7 @@ class Scrivener
134
134
  EMAIL = /\A([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*
135
135
  [\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@
136
136
  ((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+
137
- [a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)\z/ix
137
+ [a-z]{2,12})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)\z/ix
138
138
 
139
139
  def assert_email(att, error = [att, :not_email])
140
140
  if assert_present(att, error)
@@ -0,0 +1,4 @@
1
+ .PHONY: test
2
+
3
+ test:
4
+ cutest test/**/*.rb
@@ -1,21 +1,16 @@
1
1
  require "./lib/scrivener"
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = "scrivener"
5
- s.version = Scrivener::VERSION
6
- s.summary = "Validation frontend for models."
7
- s.description = "Scrivener removes the validation responsibility from models and acts as a filter for whitelisted attributes."
8
- s.authors = ["Michel Martens"]
9
- s.email = ["michel@soveran.com"]
10
- s.homepage = "http://github.com/soveran/scrivener"
11
- s.files = Dir[
12
- "LICENSE",
13
- "AUTHORS",
14
- "README.md",
15
- "Rakefile",
16
- "lib/**/*.rb",
17
- "*.gemspec",
18
- "test/**/*.rb"
19
- ]
4
+ s.name = "scrivener"
5
+ s.version = Scrivener::VERSION
6
+ s.summary = "Validation frontend for models."
7
+ s.description = "Scrivener removes the validation responsibility from models and acts as a filter for whitelisted attributes."
8
+ s.authors = ["Michel Martens"]
9
+ s.email = ["michel@soveran.com"]
10
+ s.homepage = "http://github.com/soveran/scrivener"
11
+ s.license = "MIT"
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+
20
15
  s.add_development_dependency "cutest"
21
16
  end
@@ -6,12 +6,14 @@ class A < Scrivener
6
6
  end
7
7
 
8
8
  scope do
9
- test "raise when there are extra fields" do
9
+ test "ignore extra fields" do
10
10
  atts = { :a => 1, :b => 2, :c => 3 }
11
11
 
12
- assert_raise NoMethodError do
13
- filter = A.new(atts)
14
- end
12
+ filter = A.new(atts)
13
+
14
+ atts.delete(:c)
15
+
16
+ assert_equal atts, filter.attributes
15
17
  end
16
18
 
17
19
  test "not raise when there are less fields" do
@@ -123,6 +125,9 @@ scope do
123
125
 
124
126
  filter = D.new(url: "http://google.com", email: "me@google.com")
125
127
  assert filter.valid?
128
+
129
+ filter = D.new(url: "http://example.versicherung", email: "me@example.versicherung")
130
+ assert filter.valid?
126
131
  end
127
132
  end
128
133
 
@@ -202,61 +207,118 @@ end
202
207
 
203
208
  class H < Scrivener
204
209
  attr_accessor :a
210
+ attr_accessor :b
205
211
 
206
212
  def validate
207
- assert_length :a, 3..10
213
+ assert_equal :a, "foo"
214
+ assert_equal :b, Integer
208
215
  end
209
216
  end
210
217
 
211
218
  scope do
212
- test "length validation" do
219
+ test "equality validation" do
213
220
  filter = H.new({})
214
221
 
215
222
  assert ! filter.valid?
216
- assert filter.errors[:a].include?(:not_in_range)
223
+ assert filter.errors[:a].include?(:not_equal)
224
+ assert filter.errors[:b].include?(:not_equal)
217
225
 
218
- filter = H.new(a: "fo")
226
+ filter = H.new(a: "foo", b: "bar")
219
227
  assert ! filter.valid?
220
- assert filter.errors[:a].include?(:not_in_range)
221
228
 
222
- filter = H.new(a: "foofoofoofo")
229
+ filter = H.new(a: "foo")
223
230
  assert ! filter.valid?
224
- assert filter.errors[:a].include?(:not_in_range)
231
+ assert filter.errors[:a].empty?
232
+ assert filter.errors[:b].include?(:not_equal)
225
233
 
226
- filter = H.new(a: "foo")
234
+ filter = H.new(a: "foo", b: 42)
235
+ filter.valid?
227
236
  assert filter.valid?
228
237
  end
229
238
  end
230
239
 
240
+ class Scrivener
241
+ def assert_filter(att, filter, error = nil)
242
+ filter = filter.new(send(att))
243
+
244
+ unless filter.valid?
245
+ assert(false, error || [att, filter.errors])
246
+ end
247
+ end
248
+ end
249
+
231
250
  class I < Scrivener
232
- attr_accessor :a
233
- attr_accessor :b
251
+ attr_accessor :name
252
+
253
+ def validate
254
+ assert_equal :name, "I"
255
+ end
256
+ end
257
+
258
+ class J < Scrivener
259
+ attr_accessor :name
260
+ attr_accessor :i
234
261
 
235
262
  def validate
236
- assert_equal :a, "foo"
237
- assert_equal :b, Fixnum
263
+ assert_equal :name, "J"
264
+ assert_filter :i, I
238
265
  end
239
266
  end
240
267
 
268
+ scope do
269
+ test "nested filters" do
270
+ j1 = J.new(name: "J", i: { name: "I" })
271
+ j2 = J.new(name: "J", i: { name: "H" })
272
+
273
+ assert_equal true, j1.valid?
274
+ assert_equal false, j2.valid?
275
+
276
+ errors = {
277
+ i: [{ name: [:not_equal] }]
278
+ }
279
+
280
+ assert_equal errors, j2.errors
281
+ end
282
+ end
283
+
284
+ class K < Scrivener
285
+ def validate(argument)
286
+ assert argument == "K", [:k, :not_valid]
287
+ end
288
+ end
241
289
 
242
290
  scope do
243
- test "equality validation" do
244
- filter = I.new({})
291
+ test "passing arguments" do
292
+ k = K.new({})
245
293
 
246
- assert ! filter.valid?
247
- assert filter.errors[:a].include?(:not_equal)
248
- assert filter.errors[:b].include?(:not_equal)
294
+ assert_equal true, k.valid?("K")
295
+ assert_equal false, k.valid?("L")
249
296
 
250
- filter = I.new(a: "foo", b: "bar")
251
- assert ! filter.valid?
297
+ errors = {
298
+ k: [:not_valid]
299
+ }
252
300
 
253
- filter = I.new(a: "foo")
254
- assert ! filter.valid?
255
- assert filter.errors[:a].empty?
256
- assert filter.errors[:b].include?(:not_equal)
301
+ assert_equal errors, k.errors
302
+ end
303
+ end
257
304
 
258
- filter = I.new(a: "foo", b: 42)
259
- filter.valid?
260
- assert filter.valid?
305
+ class L < Scrivener
306
+ def validate(argument, key:)
307
+ assert argument == "L" && key == "L", [:l, :not_valid]
308
+ end
309
+ end
310
+
311
+ scope do
312
+ test "passing keyword arguments" do
313
+ l = L.new({})
314
+
315
+ assert_equal true, l.valid?("L", key: "L")
316
+ assert_equal false, l.valid?("M", key: "M")
317
+
318
+ errors = {
319
+ l: [:not_valid]
320
+ }
321
+
322
+ assert_equal errors, l.errors
261
323
  end
262
324
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scrivener
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-30 00:00:00.000000000 Z
11
+ date: 2020-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cutest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: Scrivener removes the validation responsibility from models and acts
@@ -32,16 +32,21 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - LICENSE
35
+ - ".gems"
36
+ - ".gitignore"
36
37
  - AUTHORS
38
+ - CHANGELOG.md
39
+ - CONTRIBUTING
40
+ - LICENSE
37
41
  - README.md
38
- - Rakefile
39
- - lib/scrivener/validations.rb
40
42
  - lib/scrivener.rb
43
+ - lib/scrivener/validations.rb
44
+ - makefile
41
45
  - scrivener.gemspec
42
46
  - test/scrivener_test.rb
43
47
  homepage: http://github.com/soveran/scrivener
44
- licenses: []
48
+ licenses:
49
+ - MIT
45
50
  metadata: {}
46
51
  post_install_message:
47
52
  rdoc_options: []
@@ -49,17 +54,16 @@ require_paths:
49
54
  - lib
50
55
  required_ruby_version: !ruby/object:Gem::Requirement
51
56
  requirements:
52
- - - '>='
57
+ - - ">="
53
58
  - !ruby/object:Gem::Version
54
59
  version: '0'
55
60
  required_rubygems_version: !ruby/object:Gem::Requirement
56
61
  requirements:
57
- - - '>='
62
+ - - ">="
58
63
  - !ruby/object:Gem::Version
59
64
  version: '0'
60
65
  requirements: []
61
- rubyforge_project:
62
- rubygems_version: 2.0.14
66
+ rubygems_version: 3.1.2
63
67
  signing_key:
64
68
  specification_version: 4
65
69
  summary: Validation frontend for models.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- task :test do
2
- require "cutest"
3
- Cutest.run(Dir["test/*.rb"])
4
- end
5
-
6
- task :default => :test