scrivener 0.3.0 → 1.1.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 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