object_attorney 3.0.0 → 3.0.2
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/Gemfile.lock +10 -16
- data/README.md +41 -9
- data/lib/object_attorney/errors.rb +4 -3
- data/lib/object_attorney/helpers.rb +6 -4
- data/lib/object_attorney/validations/custom.rb +3 -1
- data/lib/object_attorney/version.rb +1 -1
- data/lib/object_attorney.rb +10 -9
- data/object_attorney.gemspec +3 -4
- data/spec/object_attorney/custom_validation_spec.rb +3 -3
- data/spec/object_attorney/object_attorney_spec.rb +167 -3
- data/spec/support/post.rb +8 -2
- data/spec/support/user.rb +6 -2
- metadata +13 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4d890c47532df6465b42cf292cce79ea7547269
|
4
|
+
data.tar.gz: 53f487a5a4f3f6a8ef76e107fdb3ca5d3340af06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc07794845c2f7370d4583e0ce75ea4918b4cf0de7644f69d35f2bb2c920b22e55989f311b5d5e76e35a004de6e38557caba229ef188c048afedb1540951d09b
|
7
|
+
data.tar.gz: b948a71214feb47355f3aca6caafa9970a3888a6c079e6bc3b1e09124ca3b7d6c81b3e30699059a86285085603a292d216adb8a16f3056d88d1efa91c26f2b7e
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
object_attorney (3.0.
|
4
|
+
object_attorney (3.0.1)
|
5
|
+
activemodel (~> 3)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
9
|
-
activemodel (
|
10
|
-
activesupport (=
|
11
|
-
builder (~> 3.
|
12
|
-
activesupport (
|
13
|
-
i18n (~> 0.
|
14
|
-
|
15
|
-
minitest (~> 5.1)
|
16
|
-
thread_safe (~> 0.3, >= 0.3.4)
|
17
|
-
tzinfo (~> 1.1)
|
10
|
+
activemodel (3.2.22.2)
|
11
|
+
activesupport (= 3.2.22.2)
|
12
|
+
builder (~> 3.0.0)
|
13
|
+
activesupport (3.2.22.2)
|
14
|
+
i18n (~> 0.6, >= 0.6.4)
|
15
|
+
multi_json (~> 1.0)
|
18
16
|
ast (2.3.0)
|
19
|
-
builder (3.
|
17
|
+
builder (3.0.4)
|
20
18
|
codeclimate-test-reporter (0.4.8)
|
21
19
|
simplecov (>= 0.7.1, < 1.0.0)
|
22
20
|
coderay (1.1.1)
|
@@ -25,7 +23,7 @@ GEM
|
|
25
23
|
i18n (0.7.0)
|
26
24
|
json (1.8.3)
|
27
25
|
method_source (0.8.2)
|
28
|
-
|
26
|
+
multi_json (1.12.1)
|
29
27
|
parser (2.3.1.2)
|
30
28
|
ast (~> 2.2)
|
31
29
|
powerpack (0.1.1)
|
@@ -61,16 +59,12 @@ GEM
|
|
61
59
|
simplecov-html (~> 0.10.0)
|
62
60
|
simplecov-html (0.10.0)
|
63
61
|
slop (3.6.0)
|
64
|
-
thread_safe (0.3.5)
|
65
|
-
tzinfo (1.2.2)
|
66
|
-
thread_safe (~> 0.1)
|
67
62
|
unicode-display_width (0.3.1)
|
68
63
|
|
69
64
|
PLATFORMS
|
70
65
|
ruby
|
71
66
|
|
72
67
|
DEPENDENCIES
|
73
|
-
activemodel (= 4.2.6)
|
74
68
|
codeclimate-test-reporter (= 0.4.8)
|
75
69
|
object_attorney!
|
76
70
|
pry (= 0.10.3)
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Object Attorney
|
2
|
-
|
2
|
+
This gem allows you to create use cases with ActiveModel validations and keep your model clean.
|
3
3
|
|
4
4
|
[](https://codeclimate.com/github/goncalvesjoao/object_attorney)
|
5
5
|
[](https://codeclimate.com/github/goncalvesjoao/object_attorney/coverage)
|
@@ -12,25 +12,57 @@ end
|
|
12
12
|
```
|
13
13
|
|
14
14
|
```ruby
|
15
|
-
class UserValidator <
|
15
|
+
class UserValidator < ObjectAttorney::Base
|
16
|
+
validates_presence_of :first_name
|
17
|
+
|
18
|
+
validate :last_name_present
|
19
|
+
|
20
|
+
def last_name_present(user)
|
21
|
+
return if user.last_name.present?
|
22
|
+
|
23
|
+
user.errors.add(:last_name, :blank)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
@user = User.new
|
30
|
+
|
31
|
+
UserValidator.new(@user).valid? # false
|
32
|
+
|
33
|
+
@user.errors.messages # { first_name: ["can't be blank"], last_name: ["can't be blank"] }
|
34
|
+
```
|
35
|
+
|
36
|
+
## 2) Custom Usage
|
37
|
+
```ruby
|
38
|
+
class User < ActiveRecord::Base
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class UserValidator
|
16
44
|
include ObjectAttorney
|
17
45
|
|
18
46
|
defend :user
|
19
47
|
|
20
|
-
validates_presence_of :first_name
|
21
|
-
end
|
48
|
+
validates_presence_of :first_name, if: :last_name_is_present
|
22
49
|
|
23
|
-
|
50
|
+
attr_accessor :user
|
24
51
|
|
25
|
-
|
26
|
-
|
52
|
+
def initialize(user)
|
53
|
+
@user = user
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_name_is_present(user)
|
57
|
+
user.last_name.present?
|
58
|
+
end
|
27
59
|
end
|
28
60
|
```
|
29
61
|
|
30
62
|
```ruby
|
31
|
-
@user = User.new
|
63
|
+
@user = User.new(last_name: 'Snow')
|
32
64
|
|
33
|
-
UserValidator.new(@user).
|
65
|
+
UserValidator.new(@user).invalid? # true
|
34
66
|
|
35
67
|
@user.errors.messages # { first_name: ["can't be blank"] }
|
36
68
|
```
|
@@ -16,14 +16,16 @@ module ObjectAttorney
|
|
16
16
|
if proc_or_method.is_a?(Proc)
|
17
17
|
base.instance_exec(object, &proc_or_method)
|
18
18
|
else
|
19
|
-
base
|
19
|
+
call_method!(base, proc_or_method, object)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def call_method!(base, method, *args)
|
24
|
+
unless base.respond_to?(method)
|
25
|
+
raise NotImplementedError, "#{base} does not respond to #{method}"
|
26
|
+
end
|
25
27
|
|
26
|
-
base.send(method)
|
28
|
+
base.send(method, *args)
|
27
29
|
end
|
28
30
|
|
29
31
|
def extend_errors_if_necessary(object)
|
data/lib/object_attorney.rb
CHANGED
@@ -11,9 +11,9 @@ module ObjectAttorney
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def defendant_is_innocent?
|
14
|
-
proven_innocent = defendants.
|
14
|
+
proven_innocent = defendants.map do |defendant|
|
15
15
|
innocent_of_all_accusations?(defendant)
|
16
|
-
end
|
16
|
+
end.all?
|
17
17
|
|
18
18
|
make_the_parent_guilty unless proven_innocent
|
19
19
|
|
@@ -29,13 +29,14 @@ module ObjectAttorney
|
|
29
29
|
protected ######################### PROTECTED ################################
|
30
30
|
|
31
31
|
def defendants
|
32
|
-
defendant =
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
defendant =
|
33
|
+
if parent_defendant
|
34
|
+
Helpers.extend_errors_if_necessary(parent_defendant)
|
35
|
+
|
36
|
+
Helpers.call_method!(parent_defendant, defendant_options[:name])
|
37
|
+
else
|
38
|
+
Helpers.call_method!(self, defendant_options[:name])
|
39
|
+
end
|
39
40
|
|
40
41
|
[defendant].flatten.compact
|
41
42
|
end
|
data/object_attorney.gemspec
CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.license = 'MIT'
|
11
11
|
gem.authors = ['João Gonçalves']
|
12
12
|
gem.email = ['goncalves.joao@gmail.com']
|
13
|
-
gem.summary = '
|
14
|
-
gem.description =
|
13
|
+
gem.summary = 'Allows you to keep your ActiveModel validations out of your objects'
|
14
|
+
gem.description = 'This gem allows you to create use cases with ActiveModel validations and keep your model clean'
|
15
15
|
gem.homepage = 'https://github.com/streetbees/object_attorney'
|
16
16
|
|
17
17
|
gem.files = `git ls-files`.split($/)
|
@@ -24,8 +24,7 @@ Gem::Specification.new do |gem|
|
|
24
24
|
gem.add_development_dependency 'rspec', '3.4.0'
|
25
25
|
gem.add_development_dependency 'rubocop', '0.37.2'
|
26
26
|
gem.add_development_dependency 'simplecov', '0.11.2'
|
27
|
-
gem.add_development_dependency 'activemodel', '4.2.6'
|
28
27
|
gem.add_development_dependency 'codeclimate-test-reporter', '0.4.8'
|
29
28
|
|
30
|
-
|
29
|
+
gem.add_dependency 'activemodel', '~> 3'
|
31
30
|
end
|
@@ -25,7 +25,7 @@ describe ObjectAttorney do
|
|
25
25
|
|
26
26
|
context "given a user with an invalid phone_number" do
|
27
27
|
before do
|
28
|
-
@user = User.new(
|
28
|
+
@user = User.new(phone_number: 'bad number')
|
29
29
|
@custom_validator.new(@user).valid?
|
30
30
|
end
|
31
31
|
|
@@ -35,7 +35,7 @@ describe ObjectAttorney do
|
|
35
35
|
|
36
36
|
context "and preventing the validation" do
|
37
37
|
before do
|
38
|
-
@user = User.new(
|
38
|
+
@user = User.new(phone_number: 'really bad number', dont_validate: true)
|
39
39
|
@custom_validator.new(@user).valid?
|
40
40
|
end
|
41
41
|
|
@@ -47,7 +47,7 @@ describe ObjectAttorney do
|
|
47
47
|
|
48
48
|
context "given a user with a valid phone_number" do
|
49
49
|
before do
|
50
|
-
@user = User.new(
|
50
|
+
@user = User.new(phone_number: '123 123')
|
51
51
|
@custom_validator.new(@user).valid?
|
52
52
|
end
|
53
53
|
|
@@ -2,6 +2,77 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ObjectAttorney do
|
4
4
|
|
5
|
+
context "When the defendant is nil" do
|
6
|
+
before do
|
7
|
+
@user_validator = Struct.new(:user) do
|
8
|
+
include ObjectAttorney
|
9
|
+
|
10
|
+
defend :user
|
11
|
+
|
12
|
+
validates_presence_of :first_name, unless: Proc.new { |user| user.dont_validate }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "#valid? should be true" do
|
17
|
+
expect(@user_validator.new(nil).valid?).to be true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "When the defendant is empty" do
|
22
|
+
before do
|
23
|
+
@user = User.new
|
24
|
+
@user.posts = []
|
25
|
+
|
26
|
+
@user_validator = Struct.new(:user) do
|
27
|
+
include ObjectAttorney
|
28
|
+
|
29
|
+
defend :posts, in: :user
|
30
|
+
|
31
|
+
validates_presence_of :first_name, unless: Proc.new { |user| user.dont_validate }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "#valid? should be true" do
|
36
|
+
expect(@user_validator.new(@user).valid?).to be true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "When the defendant is not defined" do
|
41
|
+
before do
|
42
|
+
@user = User.new
|
43
|
+
|
44
|
+
@user_validator = Struct.new(:user) do
|
45
|
+
include ObjectAttorney
|
46
|
+
|
47
|
+
defend :posts
|
48
|
+
|
49
|
+
validates_presence_of :first_name, unless: Proc.new { |user| user.dont_validate }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "#valid? should raise an error" do
|
54
|
+
expect { @user_validator.new(@user).valid? }.to raise_error NotImplementedError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "When the defendant is not defined on the parent" do
|
59
|
+
before do
|
60
|
+
@user = User.new
|
61
|
+
|
62
|
+
@user_validator = Struct.new(:user) do
|
63
|
+
include ObjectAttorney
|
64
|
+
|
65
|
+
defend :comments, in: :user
|
66
|
+
|
67
|
+
validates_presence_of :first_name, unless: Proc.new { |user| user.dont_validate }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "#valid? should raise an error" do
|
72
|
+
expect { @user_validator.new(@user).valid? }.to raise_error NotImplementedError
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
5
76
|
context "When the defendant is a single object" do
|
6
77
|
before do
|
7
78
|
@user = User.new
|
@@ -23,7 +94,7 @@ describe ObjectAttorney do
|
|
23
94
|
|
24
95
|
context "and the unless validation is true" do
|
25
96
|
before do
|
26
|
-
@user = User.new(
|
97
|
+
@user = User.new(dont_validate: true)
|
27
98
|
end
|
28
99
|
|
29
100
|
it "@user.errors should be empty" do
|
@@ -37,7 +108,7 @@ describe ObjectAttorney do
|
|
37
108
|
context "When the defendant is an array nested inside another object" do
|
38
109
|
before do
|
39
110
|
@user = User.new
|
40
|
-
@user.posts = [Post.new, Post.new(
|
111
|
+
@user.posts = [Post.new, Post.new(_destroy: true), nil, Post.new(title: 'yada')]
|
41
112
|
|
42
113
|
@user_validator = Struct.new(:user) do
|
43
114
|
include ObjectAttorney
|
@@ -57,8 +128,101 @@ describe ObjectAttorney do
|
|
57
128
|
it "only the first @user.posts should have errors" do
|
58
129
|
expect(@user.posts[0].errors.messages).to eq({ title: ["can't be blank"] })
|
59
130
|
expect(@user.posts[1].errors.empty?).to be true
|
60
|
-
expect(@user.posts[2]
|
131
|
+
expect(@user.posts[2]).to be_nil
|
132
|
+
expect(@user.posts[3].errors.empty?).to be true
|
61
133
|
end
|
62
134
|
end
|
63
135
|
|
136
|
+
describe "inheritance" do
|
137
|
+
|
138
|
+
context "when a use case inherits from another that has a dependant and a validation" do
|
139
|
+
before do
|
140
|
+
@user1 = User.new
|
141
|
+
@user2 = User.new
|
142
|
+
@user3 = User.new
|
143
|
+
@user4 = User.new
|
144
|
+
|
145
|
+
@user_validator1 = Class.new do
|
146
|
+
include ObjectAttorney
|
147
|
+
|
148
|
+
defend :user
|
149
|
+
|
150
|
+
validates_presence_of :first_name
|
151
|
+
|
152
|
+
attr_accessor :user
|
153
|
+
|
154
|
+
def initialize(user)
|
155
|
+
@user = user
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
@user_validator2 = Class.new(@user_validator1) do
|
160
|
+
validates_presence_of :phone_number
|
161
|
+
end
|
162
|
+
|
163
|
+
@user_validator3 = Class.new(@user_validator2) do
|
164
|
+
defend :users
|
165
|
+
|
166
|
+
attr_accessor :users
|
167
|
+
|
168
|
+
def initialize(users)
|
169
|
+
@users = users
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
@user_validator1.new(@user1).valid?
|
174
|
+
@user_validator2.new(@user2).valid?
|
175
|
+
@user_validator3.new([@user3, @user4]).valid?
|
176
|
+
end
|
177
|
+
|
178
|
+
it "@user_validator1.defendant_options should mention :user" do
|
179
|
+
expect(@user_validator1.defendant_options).to eq({ name: :user })
|
180
|
+
end
|
181
|
+
|
182
|
+
it "@user_validator2.defendant_options should mention :user" do
|
183
|
+
expect(@user_validator2.defendant_options).to eq({ name: :user })
|
184
|
+
end
|
185
|
+
|
186
|
+
it "@user_validator3.defendant_options should mention :users" do
|
187
|
+
expect(@user_validator3.defendant_options).to eq({ name: :users })
|
188
|
+
end
|
189
|
+
|
190
|
+
it "@user1.errors should ONLY mention first_name" do
|
191
|
+
expect(@user1.errors.count).to be 1
|
192
|
+
|
193
|
+
expect(@user1.errors.messages).to eq({
|
194
|
+
first_name: ["can't be blank"]
|
195
|
+
})
|
196
|
+
end
|
197
|
+
|
198
|
+
it "@user2.errors should mention first_name and phone_number" do
|
199
|
+
expect(@user2.errors.messages).to eq({
|
200
|
+
first_name: ["can't be blank"],
|
201
|
+
phone_number: ["can't be blank"]
|
202
|
+
})
|
203
|
+
|
204
|
+
expect(@user2.errors.count).to be 2
|
205
|
+
end
|
206
|
+
|
207
|
+
it "@user3.errors should mention first_name and phone_number" do
|
208
|
+
expect(@user3.errors.messages).to eq({
|
209
|
+
first_name: ["can't be blank"],
|
210
|
+
phone_number: ["can't be blank"]
|
211
|
+
})
|
212
|
+
|
213
|
+
expect(@user3.errors.count).to be 2
|
214
|
+
end
|
215
|
+
|
216
|
+
it "@user4.errors should mention first_name and phone_number" do
|
217
|
+
expect(@user4.errors.messages).to eq({
|
218
|
+
first_name: ["can't be blank"],
|
219
|
+
phone_number: ["can't be blank"]
|
220
|
+
})
|
221
|
+
|
222
|
+
expect(@user4.errors.count).to be 2
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
64
228
|
end
|
data/spec/support/post.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
-
class Post
|
1
|
+
class Post
|
2
|
+
|
3
|
+
attr_accessor :title, :_destroy
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
(attributes || {}).each { |name, value| send("#{name}=", value) }
|
7
|
+
end
|
2
8
|
|
3
9
|
def marked_for_destruction?
|
4
|
-
|
10
|
+
_destroy
|
5
11
|
end
|
6
12
|
|
7
13
|
end
|
data/spec/support/user.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
class User
|
1
|
+
class User
|
2
2
|
|
3
|
-
attr_accessor :posts
|
3
|
+
attr_accessor :first_name, :phone_number, :dont_validate, :posts
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
(attributes || {}).each { |name, value| send("#{name}=", value) }
|
7
|
+
end
|
4
8
|
|
5
9
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object_attorney
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- João Gonçalves
|
@@ -81,36 +81,35 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.11.2
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: codeclimate-test-reporter
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 4.
|
89
|
+
version: 0.4.8
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 4.
|
96
|
+
version: 0.4.8
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: activemodel
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
104
|
-
type: :
|
103
|
+
version: '3'
|
104
|
+
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
111
|
-
description: This gem allows you to
|
112
|
-
|
113
|
-
a specific use case.
|
110
|
+
version: '3'
|
111
|
+
description: This gem allows you to create use cases with ActiveModel validations
|
112
|
+
and keep your model clean
|
114
113
|
email:
|
115
114
|
- goncalves.joao@gmail.com
|
116
115
|
executables: []
|
@@ -166,7 +165,7 @@ rubyforge_project:
|
|
166
165
|
rubygems_version: 2.5.1
|
167
166
|
signing_key:
|
168
167
|
specification_version: 4
|
169
|
-
summary:
|
168
|
+
summary: Allows you to keep your ActiveModel validations out of your objects
|
170
169
|
test_files:
|
171
170
|
- spec/object_attorney/base_spec.rb
|
172
171
|
- spec/object_attorney/custom_validation_spec.rb
|