valhammer 0.2.2 → 0.3.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
2
  SHA1:
3
- metadata.gz: f5cc152c6e61d42ceb78240e85b5c864341736ad
4
- data.tar.gz: 1eb227b60d2c901dbb84105774725419574a7167
3
+ metadata.gz: 758eec1c687a507398055fdb46d849004962b1b6
4
+ data.tar.gz: bda97ef82eb60f40da4789514710c122897a35ab
5
5
  SHA512:
6
- metadata.gz: f285efa488450a71180ea6c9065c79c120a1c005a51a7c3640e9566c79ad10428d76b1af4e88fb58d3a1b64b9f5fdf88168a7c4dcdff3f0c47c2fb854aa01772
7
- data.tar.gz: b495dc9987aa836118f8eb062a0c2d7ed3079be5640c5e372520af8e99aab2225fe5adc2231b92133b54aa4be115dd377033975f60c148c1dbf9d859f0883a55
6
+ metadata.gz: 6a8dc0e51c7b2ebb78fc0a6536be61a49a7b66257807f6dd901e28736631b755c7fdebd4639d350780862af0f8de2fce2846b7a1e55566b435aaee018e1c83a7
7
+ data.tar.gz: af035d6d7dab4931dbbabe1fa1602b30fd98610e90b2ec46f8a631749b4ae734caf1774afec8f7f57f495602a6c68a1a534ca7d7aa5466713303630c06a42c89
data/.simplecov CHANGED
@@ -1,6 +1,4 @@
1
- require 'codeclimate-test-reporter'
2
- CodeClimate::TestReporter.start
3
-
1
+ SimpleCov.command_name 'rspec'
4
2
  SimpleCov.start do
5
3
  add_filter('spec')
6
4
  end
data/README.md CHANGED
@@ -82,13 +82,40 @@ Generated validations are:
82
82
  * `:length` — added to `string` columns to ensure the value fits in the
83
83
  column
84
84
 
85
- To disable a kind of validation, pass an option to the `valhammer` method:
85
+ ### Disabling Validators
86
+
87
+ Passing a block to `valhammer` allows some selective calls to `disable` to
88
+ customise the validators which are applied to your model:
89
+
90
+ ```ruby
91
+ class Widget < ActiveRecord::Base
92
+ valhammer do
93
+ disable item_code: [:presence, :uniqueness]
94
+ end
95
+ end
96
+ ```
97
+
98
+ Disabling an attribute instructs Valhammer not to apply *any* validators for
99
+ that attribute:
100
+
101
+ ```ruby
102
+ class Widget < ActiveRecord::Base
103
+ valhammer do
104
+ disable :supplier_code
105
+ end
106
+ end
107
+ ```
108
+
109
+ When disabling validations for an association, disable the validations on the
110
+ **association name**, not the name of the foreign key column:
86
111
 
87
112
  ```ruby
88
113
  class Widget < ActiveRecord::Base
89
114
  belongs_to :supplier
90
115
 
91
- valhammer uniqueness: false
116
+ valhammer do
117
+ disable supplier: :presence
118
+ end
92
119
  end
93
120
  ```
94
121
 
@@ -1,37 +1,68 @@
1
1
  module Valhammer
2
2
  module Validations
3
- VALHAMMER_DEFAULT_OPTS = { presence: true, uniqueness: true,
4
- numericality: true, length: true,
5
- inclusion: true }.freeze
3
+ class DisabledFieldConfig
4
+ def self.perform(&bl)
5
+ new.tap { |obj| obj.instance_eval(&bl) if block_given? }.to_opts
6
+ end
7
+
8
+ def initialize
9
+ @disabled_validations = {}
10
+ end
11
+
12
+ ALL = %i(presence uniqueness inclusion length numericality).freeze
13
+
14
+ def disable(opts)
15
+ opts = { opts => ALL } if opts.is_a?(Symbol)
16
+
17
+ opts.each do |k, v|
18
+ @disabled_validations[k] ||= []
19
+ @disabled_validations[k] += Array(v)
20
+ end
21
+ end
22
+
23
+ def to_opts
24
+ @disabled_validations.stringify_keys.transform_values do |v|
25
+ Hash[v.zip(Array.new(v.length, false))]
26
+ end
27
+ end
28
+ end
6
29
 
7
30
  VALHAMMER_EXCLUDED_FIELDS = %w(created_at updated_at).freeze
8
31
 
9
- private_constant :VALHAMMER_DEFAULT_OPTS, :VALHAMMER_EXCLUDED_FIELDS
32
+ private_constant :VALHAMMER_EXCLUDED_FIELDS, :DisabledFieldConfig
10
33
 
11
- def valhammer(opts = {})
34
+ def valhammer(&bl)
12
35
  @valhammer_indexes = connection.indexes(table_name)
13
- opts = VALHAMMER_DEFAULT_OPTS.merge(opts)
36
+ config = DisabledFieldConfig.perform(&bl)
37
+
14
38
  columns_hash.each do |name, column|
15
- valhammer_validate(name, column, opts)
39
+ valhammer_validate(name, column, config)
16
40
  end
17
41
  end
18
42
 
19
43
  private
20
44
 
21
- def valhammer_validate(name, column, opts)
45
+ def valhammer_validate(name, column, config)
22
46
  return if valhammer_exclude?(name)
23
47
 
24
48
  assoc_name = valhammer_assoc_name(name)
25
- if assoc_name.nil?
26
- validations = valhammer_validations(column, opts)
27
- validates(name, validations) unless validations.empty?
28
- return
29
- end
49
+ return valhammer_validate_assoc(assoc_name, column, config) if assoc_name
30
50
 
51
+ opts = valhammer_field_config(config, name)
52
+ validations = valhammer_validations(column, opts)
53
+ validates(name, validations) unless validations.empty?
54
+ end
55
+
56
+ def valhammer_validate_assoc(assoc_name, column, config)
57
+ opts = valhammer_field_config(config, assoc_name)
31
58
  return if column.null || !opts[:presence]
32
59
  validates(assoc_name, presence: true)
33
60
  end
34
61
 
62
+ def valhammer_field_config(config, field)
63
+ Hash.new(true).merge(config[field.to_s] || {})
64
+ end
65
+
35
66
  def valhammer_validations(column, opts)
36
67
  logger.debug("Valhammer generating options for #{valhammer_info(column)}")
37
68
 
@@ -66,7 +97,6 @@ module Valhammer
66
97
  return unless unique_keys.one?
67
98
 
68
99
  scope = unique_keys.first.columns[0..-2]
69
-
70
100
  validations[:uniqueness] = valhammer_unique_opts(scope)
71
101
  end
72
102
 
@@ -80,9 +110,7 @@ module Valhammer
80
110
  end
81
111
 
82
112
  def valhammer_numeric(validations, column, opts)
83
- return unless opts[:numericality]
84
-
85
- return if defined_enums.key?(column.name)
113
+ return if !opts[:numericality] || defined_enums.key?(column.name)
86
114
 
87
115
  case column.type
88
116
  when :integer
@@ -96,7 +124,6 @@ module Valhammer
96
124
 
97
125
  def valhammer_length(validations, column, opts)
98
126
  return unless opts[:length] && column.type == :string && column.limit
99
-
100
127
  validations[:length] = { maximum: column.limit }
101
128
  end
102
129
 
@@ -1,3 +1,3 @@
1
1
  module Valhammer
2
- VERSION = '0.2.2'.freeze
2
+ VERSION = '0.3.1'.freeze
3
3
  end
data/spec/db/schema.rb CHANGED
@@ -4,7 +4,7 @@ ActiveRecord::Schema.define(version: 0) do
4
4
 
5
5
  t.string :name, null: false, default: nil, limit: 100
6
6
  t.string :mail, null: false, default: nil
7
- t.string :identifier, null: false, default: nil
7
+ t.string :identifier, null: false, default: nil, limit: 100
8
8
  t.string :description, null: true, default: nil
9
9
  t.integer :age, null: true, default: nil
10
10
  t.decimal :gpa, null: false, default: 3.0
@@ -180,77 +180,114 @@ RSpec.describe Valhammer::Validations do
180
180
  it { is_expected.to include(a_validator_for(:name, :length, maximum: 100)) }
181
181
  end
182
182
 
183
- context 'with disabled validations' do
184
- around do |example|
185
- old = ActiveRecord::Base.logger
186
-
187
- begin
188
- ActiveRecord::Base.logger = Logger.new('/dev/null')
189
- example.run
190
- ensure
191
- ActiveRecord::Base.logger = old
192
- end
193
- end
194
-
183
+ context 'when passing a block' do
195
184
  let(:klass) do
196
- opts = { disabled_validator => false }
185
+ opts = disable_opts
186
+
197
187
  Class.new(ActiveRecord::Base) do
198
188
  self.table_name = 'resources'
199
189
 
200
190
  belongs_to :organisation
201
191
 
202
- valhammer(opts)
192
+ valhammer do
193
+ disable opts
194
+ end
203
195
  end
204
196
  end
205
197
 
206
198
  subject { klass.validators }
207
199
 
208
- context ':presence' do
209
- let(:disabled_validator) { :presence }
200
+ context 'disabling an attribute' do
201
+ let(:disable_opts) { :name }
202
+
203
+ it 'excludes all validators for the field' do
204
+ [:presence, :length, :uniqueness].each do |v|
205
+ expect(subject).not_to include(a_validator_for(:name, v))
206
+ end
207
+ end
208
+ end
209
+
210
+ context 'disabling a presence validator' do
211
+ let(:disable_opts) { { name: :presence } }
212
+
213
+ it 'excludes the disabled validator' do
214
+ expect(subject).not_to include(a_validator_for(:name, :presence))
215
+ end
210
216
 
211
- it 'excludes the presence validator' do
217
+ it 'includes other validators of the same type' do
218
+ expect(subject).to include(a_validator_for(:mail, :presence))
219
+ end
220
+
221
+ it 'includes other validators for the same field' do
212
222
  expect(subject)
213
- .to not_include(a_validator_for(:name, :presence))
214
- .and not_include(a_validator_for(:mail, :presence))
215
- .and not_include(a_validator_for(:identifier, :presence))
216
- .and not_include(a_validator_for(:gpa, :presence))
217
- .and not_include(a_validator_for(:organisation, :presence))
223
+ .to include(a_validator_for(:name, :length, maximum: 100))
218
224
  end
219
225
  end
220
226
 
221
- context ':inclusion' do
222
- let(:disabled_validator) { :inclusion }
227
+ context 'disabling a presence validator for an association' do
228
+ let(:disable_opts) { { organisation: :presence } }
223
229
 
224
- it 'excludes the inclusion validator' do
230
+ it 'excludes the disabled validator' do
225
231
  expect(subject)
226
- .not_to include(a_validator_for(:injected, :inclusion))
232
+ .not_to include(a_validator_for(:organisation, :presence))
233
+ end
234
+ end
235
+
236
+ context 'disabling an inclusion validator' do
237
+ let(:disable_opts) { { injected: :inclusion } }
238
+
239
+ it 'excludes the disabled validator' do
240
+ expect(subject).not_to include(a_validator_for(:injected, :inclusion))
227
241
  end
228
242
  end
229
243
 
230
- context ':uniqueness' do
231
- let(:disabled_validator) { :uniqueness }
244
+ context 'disabling a uniqueness validator' do
245
+ let(:disable_opts) { { identifier: :uniqueness } }
232
246
 
233
- it 'excludes the uniqueness validator' do
247
+ it 'excludes the disabled validator' do
234
248
  expect(subject)
235
249
  .not_to include(a_validator_for(:identifier, :uniqueness))
236
250
  end
251
+
252
+ it 'includes other validators of the same type' do
253
+ expect(subject).to include(a_validator_for(:name, :uniqueness))
254
+ end
255
+
256
+ it 'includes other validators for the same field' do
257
+ expect(subject).to include(a_validator_for(:identifier, :presence))
258
+ end
237
259
  end
238
260
 
239
- context ':numericality' do
240
- let(:disabled_validator) { :numericality }
261
+ context 'disabling a numericality validator' do
262
+ let(:disable_opts) { { gpa: :numericality } }
263
+
264
+ it 'excludes the disabled validator' do
265
+ expect(subject).not_to include(a_validator_for(:gpa, :numericality))
266
+ end
267
+
268
+ it 'includes other validators of the same type' do
269
+ expect(subject).to include(a_validator_for(:age, :numericality))
270
+ end
241
271
 
242
- it 'excludes the numericality validator' do
243
- expect(subject).to not_include(a_validator_for(:age, :numericality))
244
- .and not_include(a_validator_for(:gpa, :numericality))
272
+ it 'includes other validators for the same field' do
273
+ expect(subject).to include(a_validator_for(:gpa, :presence))
245
274
  end
246
275
  end
247
276
 
248
- context ':length' do
249
- let(:disabled_validator) { :length }
277
+ context 'disabling a length validator' do
278
+ let(:disable_opts) { { name: :length } }
250
279
 
251
- it 'excludes the length validator' do
280
+ it 'excludes the disabled validator' do
252
281
  expect(subject).not_to include(a_validator_for(:name, :length))
253
282
  end
283
+
284
+ it 'includes other validators of the same type' do
285
+ expect(subject).to include(a_validator_for(:identifier, :length))
286
+ end
287
+
288
+ it 'includes other validators for the same field' do
289
+ expect(subject).to include(a_validator_for(:name, :presence))
290
+ end
254
291
  end
255
292
  end
256
293
 
data/valhammer.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'activerecord', '> 4.1'
22
+ spec.add_dependency 'activesupport', '> 4.1'
22
23
 
23
24
  spec.add_development_dependency 'rails', '> 4.1'
24
25
  spec.add_development_dependency 'bundler'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valhammer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun Mangelsdorf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-13 00:00:00.000000000 Z
11
+ date: 2016-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rails
29
43
  requirement: !ruby/object:Gem::Requirement