object_attorney 3.0.0 → 3.0.2

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
2
  SHA1:
3
- metadata.gz: dbfd04fe687681f1030ef93cbbf32c177bb67f98
4
- data.tar.gz: b2e7ff76d84de665db33f2275e082ad6dc24122c
3
+ metadata.gz: c4d890c47532df6465b42cf292cce79ea7547269
4
+ data.tar.gz: 53f487a5a4f3f6a8ef76e107fdb3ca5d3340af06
5
5
  SHA512:
6
- metadata.gz: 416ef86c1c665c0a20ef9a9efd78ed2ab21cacd7b254bbf5282e63cf54f214bb0757020f145a404730d0c63fd6fbd06a8457461d833f706c1a7a1c3e34e61ea8
7
- data.tar.gz: 878e0a1ce4a1fbcabf50ac95dd2e7090f6f21548bf19b559fca4b1dc49ce0c939d76ca28da737cc6414c384f972a13126935dc73e2f4c9f63256a8dd83d2f92f
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.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 (4.2.6)
10
- activesupport (= 4.2.6)
11
- builder (~> 3.1)
12
- activesupport (4.2.6)
13
- i18n (~> 0.7)
14
- json (~> 1.7, >= 1.7.7)
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.2.2)
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
- minitest (5.9.0)
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
  [![Code Climate](https://codeclimate.com/github/goncalvesjoao/object_attorney/badges/gpa.svg)](https://codeclimate.com/github/goncalvesjoao/object_attorney)
5
5
  [![Test Coverage](https://codeclimate.com/github/goncalvesjoao/object_attorney/badges/coverage.svg)](https://codeclimate.com/github/goncalvesjoao/object_attorney/coverage)
@@ -12,25 +12,57 @@ end
12
12
  ```
13
13
 
14
14
  ```ruby
15
- class UserValidator < Struct.new(:user)
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
- # OR
50
+ attr_accessor :user
24
51
 
25
- class UserValidator < ObjectAttorney::Base
26
- validates_presence_of :first_name
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).valid?
65
+ UserValidator.new(@user).invalid? # true
34
66
 
35
67
  @user.errors.messages # { first_name: ["can't be blank"] }
36
68
  ```
@@ -9,9 +9,10 @@ module ObjectAttorney
9
9
  attribute
10
10
  end
11
11
 
12
- def lookup_ancestors
13
- [self]
14
- end
12
+ # Having doubts if this is really necessary
13
+ # def lookup_ancestors
14
+ # [self]
15
+ # end
15
16
  end
16
17
 
17
18
  def self.included(base_class)
@@ -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.send(proc_or_method, object)
19
+ call_method!(base, proc_or_method, object)
20
20
  end
21
21
  end
22
22
 
23
- def safe_call_method(base, method)
24
- return nil unless base.respond_to?(method)
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)
@@ -14,7 +14,9 @@ module ObjectAttorney
14
14
  end
15
15
 
16
16
  def validate(defendant)
17
- [*@methods].map { |method| @attorney.send(method, defendant) }.all?
17
+ [*@methods].all? do |method|
18
+ Helpers.call_method!(@attorney, method, defendant)
19
+ end
18
20
  end
19
21
 
20
22
  end
@@ -1,5 +1,5 @@
1
1
  module ObjectAttorney
2
2
 
3
- VERSION = '3.0.0'.freeze
3
+ VERSION = '3.0.2'.freeze
4
4
 
5
5
  end
@@ -11,9 +11,9 @@ module ObjectAttorney
11
11
  end
12
12
 
13
13
  def defendant_is_innocent?
14
- proven_innocent = defendants.all? do |defendant|
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 = Helpers.safe_call_method(self, defendant_options[:name])
33
-
34
- if parent_defendant
35
- Helpers.extend_errors_if_necessary(parent_defendant)
36
-
37
- defendant ||= parent_defendant.send(defendant_options[:name])
38
- end
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
@@ -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 = 'Ruby Form Object pattern implementation'
14
- gem.description = "This gem allows you to extract the code responsible for 'validations', 'nested objects' and 'strong parameters' from your model onto a specific class for a specific use case."
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
- # gem.add_dependency 'i18n', '~> 0.7'
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('jon', 'bad number')
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('jon', 'really bad number', true)
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('jon', '123 123')
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('', '', true)
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(nil, true), Post.new('yada')]
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].errors.empty?).to be true
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 < Struct.new(:title, :marked_for_destruction)
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
- self.marked_for_destruction
10
+ _destroy
5
11
  end
6
12
 
7
13
  end
data/spec/support/user.rb CHANGED
@@ -1,5 +1,9 @@
1
- class User < Struct.new(:first_name, :phone_number, :dont_validate)
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.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: activemodel
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.2.6
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.2.6
96
+ version: 0.4.8
97
97
  - !ruby/object:Gem::Dependency
98
- name: codeclimate-test-reporter
98
+ name: activemodel
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '='
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.4.8
104
- type: :development
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: 0.4.8
111
- description: This gem allows you to extract the code responsible for 'validations',
112
- 'nested objects' and 'strong parameters' from your model onto a specific class for
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: Ruby Form Object pattern implementation
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