scrivener 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +108 -70
  3. data/lib/scrivener.rb +12 -8
  4. data/test/scrivener_test.rb +9 -1
  5. metadata +14 -13
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a1646faeced5318ac81a17b7fc8d05b59508b0d9
4
+ data.tar.gz: 80b3fa99edfe7c6e079bafa33fe3e90870701d5d
5
+ SHA512:
6
+ metadata.gz: 207456238ab18834fa1ab9834610e19a20def26196fac1780edaee47ed6046d2581cbae5c0a07e58877c4a30b85e5a3a347b21406b0a910900ae19488c5e1ea7
7
+ data.tar.gz: 5a8fe4ca21cd06578fa4287324f44ce58420ac8c9f7d87f1dccd34e0df3348eb7c2c10aa176a2ec6dd52cce3649a68af8dc1afdc152f789af22f1b4d2caecb27
data/README.md CHANGED
@@ -23,7 +23,7 @@ and its features are a subset of Bureaucrat's. For a more robust and tested
23
23
  solution, please [check it](https://github.com/tizoc/bureaucrat).
24
24
 
25
25
  This library exists to satify the need of extracting Ohm's validations for
26
- reuse in other scenarios. By doing this, all projects using Ohm::Validations
26
+ reuse in other scenarios. By doing this, all projects using `Ohm::Validations`
27
27
  will be able to profit from extra assertions such as those provided by
28
28
  [ohm-contrib](https://github.com/cyx/ohm-contrib).
29
29
 
@@ -32,35 +32,35 @@ Usage
32
32
 
33
33
  Using Scrivener feels very natural no matter what underlying model you are
34
34
  using. As it provides its own validation and whitelisting features, you can
35
- chose to ignore the ones that come bundled with ORMs.
35
+ choose to ignore the ones that come bundled with ORMs.
36
36
 
37
37
  This short example illustrates how to move the validation and whitelisting
38
38
  responsibilities away from the model and into Scrivener:
39
39
 
40
40
  ```ruby
41
- # We use Sequel::Model in this example, but it applies to other ORMs such
42
- # as Ohm or ActiveRecord.
43
- class Article < Sequel::Model
44
-
45
- # Whitelist for mass assigned attributes.
46
- set_allowed_columns :title, :body, :state
47
-
48
- # Validations for all contexts.
49
- def validate
50
- validates_presence :title
51
- validates_presence :body
52
- validates_presence :state
53
- end
54
- end
41
+ # We use Sequel::Model in this example, but it applies to other ORMs such
42
+ # as Ohm or ActiveRecord.
43
+ class Article < Sequel::Model
44
+
45
+ # Whitelist for mass assigned attributes.
46
+ set_allowed_columns :title, :body, :state
47
+
48
+ # Validations for all contexts.
49
+ def validate
50
+ validates_presence :title
51
+ validates_presence :body
52
+ validates_presence :state
53
+ end
54
+ end
55
55
 
56
- title = "Bartleby, the Scrivener"
57
- body = "I am a rather elderly man..."
56
+ title = "Bartleby, the Scrivener"
57
+ body = "I am a rather elderly man..."
58
58
 
59
- # When using the model...
60
- article = Article.new(title: title, body: body)
59
+ # When using the model...
60
+ article = Article.new(title: title, body: body)
61
61
 
62
- article.valid? #=> false
63
- article.errors.on(:state) #=> ["cannot be empty"]
62
+ article.valid? #=> false
63
+ article.errors.on(:state) #=> ["cannot be empty"]
64
64
  ```
65
65
 
66
66
  Of course, what you would do instead is declare `:title` and `:body` as allowed
@@ -72,55 +72,94 @@ feature and in others is a minor obstacle.
72
72
  Now see what happens with Scrivener:
73
73
 
74
74
  ```ruby
75
- # Now the model has no validations or whitelists. It may still have schema
76
- # constraints, which is a good practice to enforce data integrity.
77
- class Article < Sequel::Model
78
- end
75
+ # Now the model has no validations or whitelists. It may still have schema
76
+ # constraints, which is a good practice to enforce data integrity.
77
+ class Article < Sequel::Model
78
+ end
79
+
80
+ # The attribute accessors are the only fields that will be set. If more
81
+ # fields are sent when using mass assignment, a NoMethodError exception is
82
+ # raised.
83
+ #
84
+ # Note how in this example we don't accept the status attribute.
85
+ class Edit < Scrivener
86
+ attr_accessor :title
87
+ attr_accessor :body
88
+
89
+ def validate
90
+ assert_present :title
91
+ assert_present :body
92
+ end
93
+ end
94
+
95
+ edit = Edit.new(title: title, body: body)
96
+ edit.valid? #=> true
97
+
98
+ article = Article.new(edit.attributes)
99
+ article.save
100
+
101
+ # And now we only ask for the status.
102
+ class Publish < Scrivener
103
+ attr_accessor :status
104
+
105
+ def validate
106
+ assert_format :status, /^(published|draft)$/
107
+ end
108
+ end
109
+
110
+ publish = Publish.new(status: "published")
111
+ publish.valid? #=> true
112
+
113
+ article.update_attributes(publish.attributes)
114
+
115
+ # If we try to change other fields...
116
+ publish = Publish.new(status: "published", title: "foo")
117
+ #=> NoMethodError: undefined method `title=' for #<Publish...>
118
+ ```
79
119
 
80
- # The attribute accessors are the only fields that will be set. If more
81
- # fields are sent when using mass assignment, a NoMethodError exception is
82
- # raised.
83
- #
84
- # Note how in this example we don't ask the name on signup.
85
- class Edit < Scrivener
86
- attr_accessor :title
87
- attr_accessor :body
88
-
89
- def validate
90
- assert_present :title
91
- assert_present :body
92
- end
93
- end
120
+ It's important to note that using Scrivener implies a greater risk than using
121
+ the model validations. Having a central repository of mass assignable
122
+ attributes and validations is more secure in most scenarios.
123
+
124
+ Slices
125
+ ------
94
126
 
95
- edit = Edit.new(title: title, body: body)
96
- edit.valid? #=> true
127
+ If you don't need all the attributes after the filtering is done,
128
+ you can fetch just the ones you need. For example:
97
129
 
98
- article = Article.new(edit.attributes)
99
- article.save
130
+ ```ruby
131
+ class SignUp < Scrivener
132
+ attr_accessor :email
133
+ attr_accessor :password
134
+ attr_accessor :password_confirmation
100
135
 
101
- # And now we only ask for the status.
102
- class Publish < Scrivener
103
- attr_accessor :status
136
+ def validate
137
+ assert_email :email
104
138
 
105
- def validate
106
- assert_format :status, /^(published|draft)$/
107
- end
139
+ if assert_present :password
140
+ assert_equal :password, :password_confirmation
108
141
  end
142
+ end
109
143
 
110
- publish = Publish.new(status: "published")
111
- publish.valid? #=> true
144
+ def assert_equal(f1, f2)
145
+ assert send(f1) == send(f2), [f1, f2, :not_equal]
146
+ end
147
+ end
112
148
 
113
- article.update_attributes(publish.attributes)
149
+ filter = SignUp.new(email: "info@example.com",
150
+ password: "monkey",
151
+ password_confirmation: "monkey")
114
152
 
115
- # If we try to change other fields...
116
- publish = Publish.new(status: "published", title: "foo")
117
- #=> NoMethodError: undefined method `title=' for #<Publish...>
118
- ```
119
153
 
120
- It's important to note that using Scrivener implies a greater risk than using
121
- the model validations. Having a central repository of mass assignable
122
- attributes and validations is more secure in most scenarios.
154
+ # If the validation succeeds, we only need email and password to
155
+ # create a new user, and we can discard the password_confirmation.
156
+ if filter.valid?
157
+ User.create(filter.slice(:email, :password))
158
+ end
159
+ ```
123
160
 
161
+ By calling `slice` with a list of attributes, you get a hash with only
162
+ those key/value pairs.
124
163
 
125
164
  Assertions
126
165
  -----------
@@ -135,9 +174,9 @@ second parameter to the list of errors if the first parameter evaluates
135
174
  to false.
136
175
 
137
176
  ``` ruby
138
- def assert(value, error)
139
- value or errors[error.first].push(error.last) && false
140
- end
177
+ def assert(value, error)
178
+ value or errors[error.first].push(error.last) && false
179
+ end
141
180
  ```
142
181
 
143
182
  ### assert_present
@@ -174,9 +213,9 @@ Checks that a given field is contained within a set of values (i.e.
174
213
  like an `ENUM`).
175
214
 
176
215
  ``` ruby
177
- def validate
178
- assert_member :state, %w{pending paid delivered}
179
- end
216
+ def validate
217
+ assert_member :state, %w{pending paid delivered}
218
+ end
180
219
  ```
181
220
 
182
221
  The error code for this assertion is `:not_valid`
@@ -186,9 +225,9 @@ The error code for this assertion is `:not_valid`
186
225
  Checks that a given field's length falls under a specified range.
187
226
 
188
227
  ``` ruby
189
- def validate
190
- assert_length :username, 3..20
191
- end
228
+ def validate
229
+ assert_length :username, 3..20
230
+ end
192
231
  ```
193
232
 
194
233
  The error code for this assertion is `:not_in_range`.
@@ -200,7 +239,6 @@ of the word. Valid numbers are: 0.1, .1, 1, 1.1, 3.14159, etc.
200
239
 
201
240
  The error code for this assertion is `:not_decimal`.
202
241
 
203
-
204
242
  Installation
205
243
  ------------
206
244
 
@@ -1,16 +1,13 @@
1
- require File.expand_path("scrivener/validations", File.dirname(__FILE__))
1
+ require_relative "scrivener/validations"
2
2
 
3
3
  class Scrivener
4
- VERSION = "0.0.3"
4
+ VERSION = "0.1.0"
5
5
 
6
6
  include Validations
7
7
 
8
8
  # Initialize with a hash of attributes and values.
9
9
  # If extra attributes are sent, a NoMethodError exception will be raised.
10
10
  #
11
- # The grand daddy of all assertions. If you want to build custom
12
- # assertions, or even quick and dirty ones, you can simply use this method.
13
- #
14
11
  # @example
15
12
  #
16
13
  # class EditPost < Scrivener
@@ -37,8 +34,8 @@ class Scrivener
37
34
  # # Now it's safe to initialize the model.
38
35
  # post = Post.new(edit.attributes)
39
36
  # post.save
40
- def initialize(attrs)
41
- attrs.each do |key, val|
37
+ def initialize(atts)
38
+ atts.each do |key, val|
42
39
  send(:"#{key}=", val)
43
40
  end
44
41
  end
@@ -54,5 +51,12 @@ class Scrivener
54
51
  end
55
52
  end
56
53
  end
57
- end
58
54
 
55
+ def slice(*keys)
56
+ Hash.new.tap do |atts|
57
+ keys.each do |att|
58
+ atts[att] = send(att)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -27,6 +27,14 @@ scope do
27
27
 
28
28
  assert_equal atts, s.attributes
29
29
  end
30
+
31
+ test "return only the required attributes" do
32
+ atts = { :a => 1, :b => 2 }
33
+
34
+ s = S.new(atts)
35
+
36
+ assert_equal s.slice(:a), { :a => 1 }
37
+ end
30
38
  end
31
39
 
32
40
  class T < Scrivener
@@ -190,4 +198,4 @@ scope do
190
198
  assert p.valid?
191
199
  end
192
200
  end
193
- end
201
+ end
metadata CHANGED
@@ -1,27 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scrivener
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michel Martens
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-01-24 00:00:00.000000000 Z
11
+ date: 2013-04-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: cutest
16
- requirement: &2156191960 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
- version_requirements: *2156191960
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
25
27
  description: Scrivener removes the validation responsibility from models and acts
26
28
  as a filter for whitelisted attributes.
27
29
  email:
@@ -40,26 +42,25 @@ files:
40
42
  - test/scrivener_test.rb
41
43
  homepage: http://github.com/soveran/scrivener
42
44
  licenses: []
45
+ metadata: {}
43
46
  post_install_message:
44
47
  rdoc_options: []
45
48
  require_paths:
46
49
  - lib
47
50
  required_ruby_version: !ruby/object:Gem::Requirement
48
- none: false
49
51
  requirements:
50
- - - ! '>='
52
+ - - '>='
51
53
  - !ruby/object:Gem::Version
52
54
  version: '0'
53
55
  required_rubygems_version: !ruby/object:Gem::Requirement
54
- none: false
55
56
  requirements:
56
- - - ! '>='
57
+ - - '>='
57
58
  - !ruby/object:Gem::Version
58
59
  version: '0'
59
60
  requirements: []
60
61
  rubyforge_project:
61
- rubygems_version: 1.8.10
62
+ rubygems_version: 2.0.3
62
63
  signing_key:
63
- specification_version: 3
64
+ specification_version: 4
64
65
  summary: Validation frontend for models.
65
66
  test_files: []