mv-core 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +190 -57
- data/lib/mv-core.rb +2 -0
- data/lib/mv/core/active_record/base_decorator.rb +21 -0
- data/lib/mv/core/validation/absence.rb +4 -0
- data/lib/mv/core/validation/active_model_presenter/absence.rb +15 -0
- data/lib/mv/core/validation/active_model_presenter/base.rb +44 -0
- data/lib/mv/core/validation/active_model_presenter/exclusion.rb +19 -0
- data/lib/mv/core/validation/active_model_presenter/factory.rb +51 -0
- data/lib/mv/core/validation/active_model_presenter/inclusion.rb +19 -0
- data/lib/mv/core/validation/active_model_presenter/length.rb +19 -0
- data/lib/mv/core/validation/active_model_presenter/presence.rb +15 -0
- data/lib/mv/core/validation/active_model_presenter/uniqueness.rb +15 -0
- data/lib/mv/core/validation/base.rb +8 -0
- data/lib/mv/core/validation/builder/base.rb +4 -1
- data/lib/mv/core/validation/builder/length.rb +8 -2
- data/lib/mv/core/validation/custom.rb +6 -0
- data/lib/mv/core/validation/exclusion.rb +6 -0
- data/lib/mv/core/validation/inclusion.rb +6 -0
- data/lib/mv/core/validation/length.rb +24 -2
- data/lib/mv/core/validation/presence.rb +6 -0
- data/lib/mv/core/validation/uniqueness.rb +4 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab1d009f28ad7d42d5c3bd4aa052c3bac79a25dd
|
4
|
+
data.tar.gz: 3c1db440ab887e8f16efeb8f43ead8fde721ce3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d27d2949d1dcf0ae10ae704b0a4cca6efecbd52b4799b13b70717b4e692866af265627beec0567993c227a7e733cd6c84630e9f5ce8365c23f56db814314c50
|
7
|
+
data.tar.gz: 4b325c5abde253836ecc0b6ed094494906fc3b699b0005e686afc1ef50042168ee733f39e18f41448bdf7c35c335fd3aba137e31ec800d30f58582a3011aeda6
|
data/README.md
CHANGED
@@ -1,91 +1,118 @@
|
|
1
|
-
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/vprokopchuk256/mv-core/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
2
1
|
[![Build Status](https://travis-ci.org/vprokopchuk256/mv-core.svg?branch=master)](https://travis-ci.org/vprokopchuk256/mv-core)
|
3
2
|
[![Coverage Status](https://coveralls.io/repos/vprokopchuk256/mv-core/badge.png?branch=master)](https://coveralls.io/r/vprokopchuk256/mv-core?branch=master)
|
4
3
|
[![Gem Version](https://badge.fury.io/rb/mv-core.svg)](http://badge.fury.io/rb/mv-core)
|
5
4
|
|
5
|
+
# Define validations in database and use them in model
|
6
|
+
|
7
|
+
Project ```Migration Validators``` (MV) makes it possible for RoR developer to define validations directly in db and then bubble them up to model so they available as normal ActiveModel::Validations there. And all that without code duplication.
|
8
|
+
|
6
9
|
# Abbreviations
|
7
10
|
|
8
11
|
MV - Migration Validators Projects. All gems that belongs to that project are prefixed with mv-*
|
9
12
|
|
10
|
-
#
|
13
|
+
#Table Of Contents
|
14
|
+
* [Why Migration Validators](#why-migration-validators)
|
15
|
+
* [How It Works](#how-it-works)
|
16
|
+
* [Examples](#examples)
|
17
|
+
* [Installation](#installation)
|
18
|
+
* [PostgreSQL](#postgresql)
|
19
|
+
* [MySQL](#mysql)
|
20
|
+
* [SQLite](#sqlite)
|
21
|
+
* [Integration with ActiveRecord](#integration-with-activerecord)
|
22
|
+
* [Tasks](#tasks)
|
23
|
+
* [Drivers](#drivers)
|
24
|
+
* [Version History](#version history)
|
25
|
+
* [Contributing](#contributing)
|
11
26
|
|
12
|
-
|
27
|
+
# Why `Migration Validators`
|
13
28
|
|
14
|
-
|
29
|
+
It's commonly accepted in RoR community to ignore database constraints and define data validations in ActiveModel. In most cases such approach is perfectly acceptable and allows developer to concentrate on business logic rather than on writing database - specific code.
|
15
30
|
|
16
|
-
|
31
|
+
But when your application grows significantly then possibility of the data error with such approach became more tangible. Data consistency could be violated in many ways: directly ( with db console for ex ), as result of some error in the code, by other application if database is shared.
|
17
32
|
|
18
|
-
|
33
|
+
DB constraints could help in such case. But there are several reasons why they are not widely spread in RoR: such constraints are DB - specific in most cases and their management is quite tricky.
|
19
34
|
|
20
|
-
|
35
|
+
The goal of the `Migration Validators` project is to resolve those problems and make DB constraints management straightforward
|
21
36
|
|
22
|
-
|
37
|
+
# How It Works
|
23
38
|
|
24
|
-
|
25
|
-
gem install mv-postgresql
|
26
|
-
```
|
39
|
+
`Migration Validators` project uses 3 database constructs to define validations: ```trigger```, ```check constraint```, ```index```
|
27
40
|
|
28
|
-
|
41
|
+
Most of the validations could be defined in several ways: as condition inside trigger, as condition inside check constraint or as index ( for ```uniqueness```)
|
29
42
|
|
30
|
-
|
31
|
-
gem install mv-mysql
|
32
|
-
```
|
43
|
+
In most cases developer can select how and where validation should be implemented. By default most optimal way is proposed.
|
33
44
|
|
34
|
-
|
45
|
+
For example: ```uniqueness``` validation is defined as unique index by default. But developer can select other way - trigger of check constraint. Each way has own advantages and disadvantages
|
35
46
|
|
36
|
-
|
37
|
-
gem install mv-sqlite
|
38
|
-
```
|
39
|
-
|
40
|
-
# Usage
|
47
|
+
# Examples
|
41
48
|
|
42
49
|
Create new table:
|
43
50
|
|
44
51
|
```ruby
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
def change
|
53
|
+
create_table do |t|
|
54
|
+
t.string :str_column, validates: { uniqueness: :true,
|
55
|
+
inclusion: { in: 1..3 }}
|
56
|
+
t.column :column_name, :integer, validates: { exclusion: { in: [1,2,3]}}
|
57
|
+
end
|
49
58
|
end
|
50
59
|
```
|
51
60
|
|
52
61
|
Modify existing table:
|
53
62
|
|
54
63
|
```ruby
|
55
|
-
|
56
|
-
|
57
|
-
|
64
|
+
def up
|
65
|
+
change_table do |t|
|
66
|
+
t.change :str_column, :integer, validates: { exclusion: { in: [1,2,3] }}
|
67
|
+
t.validates :column_name, inclusion: { in: 1..3 }
|
68
|
+
end
|
58
69
|
end
|
59
|
-
```
|
60
70
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
71
|
+
def down
|
72
|
+
change_table do |t|
|
73
|
+
t.change :str_column, :integer, validates: { exclusion: false }
|
74
|
+
t.validates :column_name, inclusion: false
|
75
|
+
end
|
76
|
+
end
|
65
77
|
```
|
66
78
|
|
67
|
-
|
79
|
+
Update validation definition:
|
68
80
|
|
69
81
|
```ruby
|
70
|
-
|
71
|
-
|
82
|
+
def up
|
83
|
+
validates :table_name, :str_column, exclusion: { in: [1,2,3] }
|
84
|
+
end
|
85
|
+
|
86
|
+
def down
|
87
|
+
validates :table_name, :str_column, exclusion: false
|
72
88
|
end
|
73
|
-
validates :table_name, :str_column, exclusion: false
|
74
89
|
```
|
75
90
|
|
76
|
-
There are many ways to define desired database constraint. And those ways might vary for each RDBMS. One could define the way how
|
91
|
+
There are many ways to define desired database constraint. And those ways might vary for each RDBMS. One could define the way how constraint should be
|
77
92
|
defined in DB:
|
78
93
|
|
79
94
|
as trigger:
|
80
95
|
|
81
96
|
```ruby
|
82
|
-
|
97
|
+
def up
|
98
|
+
validates :table_name, :str_column, uniqueness: { as: :trigger }
|
99
|
+
end
|
100
|
+
|
101
|
+
def down
|
102
|
+
validates :table_name, :str_column, uniqueness: { as: :index }
|
103
|
+
end
|
83
104
|
```
|
84
105
|
|
85
106
|
as check constraint:
|
86
107
|
|
87
108
|
```ruby
|
88
|
-
|
109
|
+
def up
|
110
|
+
validates :table_name, :str_column, uniqueness: { as: :check }
|
111
|
+
end
|
112
|
+
|
113
|
+
def down
|
114
|
+
validates :table_name, :str_column, uniqueness: false
|
115
|
+
end
|
89
116
|
```
|
90
117
|
|
91
118
|
Also there is possibility to define when validations should occur:
|
@@ -93,21 +120,39 @@ This gem is not intended to be installed directly and referenced from within the
|
|
93
120
|
when new record created:
|
94
121
|
|
95
122
|
```ruby
|
96
|
-
|
123
|
+
def up
|
124
|
+
validates :table_name, :str_column, uniqueness: { on: :create }
|
125
|
+
end
|
126
|
+
|
127
|
+
def down
|
128
|
+
validates :table_name, :str_column, uniqueness: false
|
129
|
+
end
|
97
130
|
```
|
98
131
|
|
99
132
|
or when existing record updated:
|
100
133
|
|
101
134
|
```ruby
|
102
|
-
|
135
|
+
def up
|
136
|
+
validates :table_name, :str_column, uniqueness: { on: :update }
|
137
|
+
end
|
138
|
+
|
139
|
+
def down
|
140
|
+
validates :table_name, :str_column, uniqueness: { on: :save }
|
141
|
+
end
|
103
142
|
```
|
104
143
|
|
105
144
|
And if you need to define some custom validation you can use custom validation (version >= 2.1 is required):
|
106
145
|
|
107
146
|
```ruby
|
108
|
-
|
109
|
-
|
110
|
-
|
147
|
+
def up
|
148
|
+
validates :table_name, :str_column,
|
149
|
+
custom: { statement: 'LENGTH(TRIM({str_column})) > 10',
|
150
|
+
on: :update }
|
151
|
+
end
|
152
|
+
|
153
|
+
def down
|
154
|
+
validates :table_name, :str_column, custom: false
|
155
|
+
end
|
111
156
|
```
|
112
157
|
|
113
158
|
as result only values with length greater than 10 will be allowed and that condition will be implemented inside ON UPDATE trigger
|
@@ -115,20 +160,99 @@ This gem is not intended to be installed directly and referenced from within the
|
|
115
160
|
Almost all validations supports shorter notation (simplification) that is not compatible with ActiveRecord validation but much shorter (version >= 2.1 is required):
|
116
161
|
|
117
162
|
```ruby
|
118
|
-
|
163
|
+
def up
|
164
|
+
validates :table_name, :str_column, uniqueness: true, presence: true
|
165
|
+
end
|
166
|
+
|
167
|
+
def down
|
168
|
+
validates :table_name, :str_column, uniqueness: false, presence: false
|
169
|
+
end
|
119
170
|
```
|
120
171
|
|
121
172
|
```ruby
|
122
|
-
|
173
|
+
def up
|
174
|
+
validates :table_name, :str_column, length: 1..3
|
175
|
+
end
|
176
|
+
|
177
|
+
def down
|
178
|
+
validates :table_name, :str_column, length: false
|
179
|
+
end
|
123
180
|
```
|
124
181
|
|
125
182
|
```ruby
|
126
|
-
|
183
|
+
def up
|
184
|
+
validates :table_name, :str_column, custom:
|
185
|
+
'LENGTH(TRIM({str_column})) > 10'
|
186
|
+
end
|
187
|
+
|
188
|
+
def down
|
189
|
+
validates :table_name, :str_column, custom: false
|
190
|
+
end
|
127
191
|
```
|
128
192
|
|
129
|
-
Supported validators, simplification and their properties might vary from one db driver to another. See detailed properties description in correspondent driver section.
|
193
|
+
Supported validators, simplification and their properties might vary from one db driver to another. See detailed properties description in correspondent [driver](#drivers) section.
|
130
194
|
|
131
|
-
#
|
195
|
+
# Installation
|
196
|
+
|
197
|
+
`mv-core` is a set of core classes that are used everywhere across `Migration Validators` project gems.
|
198
|
+
|
199
|
+
This gem is not intended to be installed directly and referenced from within the application. You should rather install appropriate driver.
|
200
|
+
|
201
|
+
### PostgreSQL:
|
202
|
+
|
203
|
+
```
|
204
|
+
gem install mv-postgresql
|
205
|
+
```
|
206
|
+
|
207
|
+
### MySQL:
|
208
|
+
|
209
|
+
```
|
210
|
+
gem install mv-mysql
|
211
|
+
```
|
212
|
+
|
213
|
+
### SQLite:
|
214
|
+
|
215
|
+
```
|
216
|
+
gem install mv-sqlite
|
217
|
+
```
|
218
|
+
|
219
|
+
# Integration With ActiveRecord
|
220
|
+
|
221
|
+
You can level up validations that are defined in DB to your model using `enforce_migration_validations` method.
|
222
|
+
|
223
|
+
Example:
|
224
|
+
|
225
|
+
migration:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
def change
|
229
|
+
create_table :posts do |t|
|
230
|
+
t.string :title, presence: { message: "can't be blank", as: :trigger }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
```
|
234
|
+
|
235
|
+
model:
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
class Post << ActiveRecord::Base
|
239
|
+
enforce_migration_validations
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
console:
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
p = Post.new(title: nil)
|
247
|
+
|
248
|
+
p.valid?
|
249
|
+
=> false
|
250
|
+
|
251
|
+
p.errors.full_messages
|
252
|
+
=> ["Title can't be blank"]
|
253
|
+
```
|
254
|
+
|
255
|
+
# Tasks
|
132
256
|
|
133
257
|
Show all constraints on the specified tables:
|
134
258
|
|
@@ -188,8 +312,22 @@ So - see detailed info here:
|
|
188
312
|
* MySQL: https://github.com/vprokopchuk256/mv-mysql
|
189
313
|
* SQLite: https://github.com/vprokopchuk256/mv-sqlite
|
190
314
|
|
191
|
-
##
|
192
|
-
|
315
|
+
## Version History
|
316
|
+
|
317
|
+
**(2.0.0)** (17 Jan, 2015)
|
318
|
+
|
319
|
+
* Completely rewritten. Migrated to Ruby 2.0 and RoR 4
|
320
|
+
|
321
|
+
**(2.1.0)** (22 Jan, 2015)
|
322
|
+
|
323
|
+
* Custom validation
|
324
|
+
|
325
|
+
**(2.2.0)** (28 Jan, 2015)
|
326
|
+
|
327
|
+
* Integration with ActiveRecord
|
328
|
+
|
329
|
+
## Contributing
|
330
|
+
|
193
331
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
194
332
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
195
333
|
* Fork the project
|
@@ -197,8 +335,3 @@ So - see detailed info here:
|
|
197
335
|
* Commit and push until you are happy with your contribution
|
198
336
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
199
337
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
200
|
-
|
201
|
-
## Copyright
|
202
|
-
|
203
|
-
Copyright (c) 2015 Valeriy Prokopchuk. See LICENSE.txt for
|
204
|
-
further details.
|
data/lib/mv-core.rb
CHANGED
@@ -6,6 +6,7 @@ require 'mv/core/active_record/connection_adapters/table_definition_decorator'
|
|
6
6
|
require 'mv/core/active_record/connection_adapters/table_decorator'
|
7
7
|
require 'mv/core/active_record/schema_dumper_decorator'
|
8
8
|
require 'mv/core/active_record/schema_decorator'
|
9
|
+
require 'mv/core/active_record/base_decorator'
|
9
10
|
require 'mv/core/active_record/migration_decorator'
|
10
11
|
require 'mv/core/active_record/migration/command_recorder_decorator'
|
11
12
|
require 'mv/core/railtie'
|
@@ -15,6 +16,7 @@ ActiveSupport.on_load(:active_record) do
|
|
15
16
|
::ActiveRecord::ConnectionAdapters::Table.send(:prepend, Mv::Core::ActiveRecord::ConnectionAdapters::TableDecorator)
|
16
17
|
::ActiveRecord::SchemaDumper.send(:prepend, Mv::Core::ActiveRecord::SchemaDumperDecorator)
|
17
18
|
::ActiveRecord::Schema.send(:prepend, Mv::Core::ActiveRecord::SchemaDecorator)
|
19
|
+
::ActiveRecord::Base.send(:extend, Mv::Core::ActiveRecord::BaseDecorator)
|
18
20
|
::ActiveRecord::Migration.send(:prepend, Mv::Core::ActiveRecord::MigrationDecorator)
|
19
21
|
::ActiveRecord::Migration::CommandRecorder.send(:prepend, Mv::Core::ActiveRecord::Migration::CommandRecorderDecorator)
|
20
22
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'mv/core/validation/active_model_presenter/factory'
|
2
|
+
|
3
|
+
module Mv
|
4
|
+
module Core
|
5
|
+
module ActiveRecord
|
6
|
+
module BaseDecorator
|
7
|
+
def self.included(base)
|
8
|
+
Mv::Core::Db::MigrationValidator.where(table_name: base.table_name).each do |validator|
|
9
|
+
presenter = Mv::Core::Validation::ActiveModelPresenter::Factory.create_presenter(validator.validation)
|
10
|
+
|
11
|
+
base.validates(presenter.column_name, presenter.options) if presenter
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def enforce_migration_validations
|
16
|
+
include BaseDecorator
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Mv
|
2
|
+
module Core
|
3
|
+
module Validation
|
4
|
+
module ActiveModelPresenter
|
5
|
+
class Base
|
6
|
+
attr_reader :validation
|
7
|
+
|
8
|
+
delegate :column_name, to: :validation
|
9
|
+
|
10
|
+
def initialize(validation)
|
11
|
+
@validation = validation
|
12
|
+
end
|
13
|
+
|
14
|
+
def options
|
15
|
+
unless @options
|
16
|
+
@options = option_names.inject({}) do |res, option_name|
|
17
|
+
option_value = validation.send(option_name)
|
18
|
+
res[option_name] = option_value if user_options.has_key?(option_name) &&
|
19
|
+
!option_value.nil?
|
20
|
+
res
|
21
|
+
end
|
22
|
+
|
23
|
+
@options = true if @options.blank?
|
24
|
+
@options = { validation_name => @options }
|
25
|
+
end
|
26
|
+
|
27
|
+
@options
|
28
|
+
end
|
29
|
+
|
30
|
+
def option_names
|
31
|
+
[:on, :allow_blank, :allow_nil, :message]
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def user_options
|
38
|
+
@user_options ||= validation.options.symbolize_keys
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'mv/core/validation/active_model_presenter/base'
|
2
|
+
|
3
|
+
module Mv
|
4
|
+
module Core
|
5
|
+
module Validation
|
6
|
+
module ActiveModelPresenter
|
7
|
+
class Exclusion < Base
|
8
|
+
def option_names
|
9
|
+
super + [:in]
|
10
|
+
end
|
11
|
+
|
12
|
+
def validation_name
|
13
|
+
:exclusion
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'mv/core/validation/active_model_presenter/exclusion'
|
2
|
+
require 'mv/core/validation/active_model_presenter/inclusion'
|
3
|
+
require 'mv/core/validation/active_model_presenter/length'
|
4
|
+
require 'mv/core/validation/active_model_presenter/presence'
|
5
|
+
require 'mv/core/validation/active_model_presenter/absence'
|
6
|
+
require 'mv/core/validation/active_model_presenter/uniqueness'
|
7
|
+
|
8
|
+
module Mv
|
9
|
+
module Core
|
10
|
+
module Validation
|
11
|
+
module ActiveModelPresenter
|
12
|
+
class Factory
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
def create_presenter validation
|
16
|
+
klass = factory_map[validation.class]
|
17
|
+
|
18
|
+
klass.new(validation) if klass
|
19
|
+
end
|
20
|
+
|
21
|
+
def register_presenter validation_class, presenter_class
|
22
|
+
factory_map[validation_class] = presenter_class
|
23
|
+
end
|
24
|
+
|
25
|
+
def register_presenters opts
|
26
|
+
opts.each do |validation_class, presenter_class|
|
27
|
+
register_presenter(validation_class, presenter_class)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
delegate :create_presenter, :register_presenter, :register_presenters, to: :instance
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def factory_map
|
38
|
+
@factory_map ||= {
|
39
|
+
Mv::Core::Validation::Exclusion => Mv::Core::Validation::ActiveModelPresenter::Exclusion,
|
40
|
+
Mv::Core::Validation::Inclusion => Mv::Core::Validation::ActiveModelPresenter::Inclusion,
|
41
|
+
Mv::Core::Validation::Length => Mv::Core::Validation::ActiveModelPresenter::Length,
|
42
|
+
Mv::Core::Validation::Presence => Mv::Core::Validation::ActiveModelPresenter::Presence,
|
43
|
+
Mv::Core::Validation::Absence => Mv::Core::Validation::ActiveModelPresenter::Absence,
|
44
|
+
Mv::Core::Validation::Uniqueness => Mv::Core::Validation::ActiveModelPresenter::Uniqueness,
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'mv/core/validation/active_model_presenter/base'
|
2
|
+
|
3
|
+
module Mv
|
4
|
+
module Core
|
5
|
+
module Validation
|
6
|
+
module ActiveModelPresenter
|
7
|
+
class Inclusion < Base
|
8
|
+
def option_names
|
9
|
+
super + [:in]
|
10
|
+
end
|
11
|
+
|
12
|
+
def validation_name
|
13
|
+
:inclusion
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'mv/core/validation/active_model_presenter/base'
|
2
|
+
|
3
|
+
module Mv
|
4
|
+
module Core
|
5
|
+
module Validation
|
6
|
+
module ActiveModelPresenter
|
7
|
+
class Length < Base
|
8
|
+
def option_names
|
9
|
+
super + [:is, :in, :within, :maximum, :minimum, :too_short, :too_long]
|
10
|
+
end
|
11
|
+
|
12
|
+
def validation_name
|
13
|
+
:length
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -49,6 +49,10 @@ module Mv
|
|
49
49
|
[:save, :create].include?(on.try(:to_sym))
|
50
50
|
end
|
51
51
|
|
52
|
+
def full_message
|
53
|
+
compose_full_message(message)
|
54
|
+
end
|
55
|
+
|
52
56
|
protected
|
53
57
|
|
54
58
|
def available_as
|
@@ -87,6 +91,10 @@ module Mv
|
|
87
91
|
false
|
88
92
|
end
|
89
93
|
|
94
|
+
def compose_full_message message
|
95
|
+
"#{column_name.to_s.camelize} #{message}"
|
96
|
+
end
|
97
|
+
|
90
98
|
private
|
91
99
|
|
92
100
|
def trigger?
|
@@ -7,7 +7,6 @@ module Mv
|
|
7
7
|
|
8
8
|
delegate :table_name,
|
9
9
|
:column_name,
|
10
|
-
:message,
|
11
10
|
:allow_nil,
|
12
11
|
:allow_blank, to: :validation
|
13
12
|
|
@@ -16,6 +15,10 @@ module Mv
|
|
16
15
|
end
|
17
16
|
|
18
17
|
protected
|
18
|
+
|
19
|
+
def message
|
20
|
+
validation.full_message
|
21
|
+
end
|
19
22
|
|
20
23
|
def column_reference
|
21
24
|
column_name
|
@@ -10,8 +10,6 @@ module Mv
|
|
10
10
|
:is,
|
11
11
|
:maximum,
|
12
12
|
:minimum,
|
13
|
-
:too_short,
|
14
|
-
:too_long,
|
15
13
|
to: :validation
|
16
14
|
|
17
15
|
def conditions
|
@@ -29,6 +27,14 @@ module Mv
|
|
29
27
|
|
30
28
|
protected
|
31
29
|
|
30
|
+
def too_short
|
31
|
+
validation.full_too_short
|
32
|
+
end
|
33
|
+
|
34
|
+
def too_long
|
35
|
+
validation.full_too_long
|
36
|
+
end
|
37
|
+
|
32
38
|
def apply_in stmt
|
33
39
|
[{ statement: self.in.is_a?(Range) ? "LENGTH(#{stmt}) BETWEEN #{self.in.min} AND #{self.in.max}" :
|
34
40
|
"LENGTH(#{stmt}) IN (#{self.in.join(', ')})",
|
@@ -29,15 +29,37 @@ module Mv
|
|
29
29
|
@is = opts[:is]
|
30
30
|
@maximum = opts[:maximum]
|
31
31
|
@minimum = opts[:minimum]
|
32
|
-
@too_long = opts[:too_long]
|
33
|
-
@too_short = opts[:too_short]
|
32
|
+
@too_long = opts[:too_long] || default_too_long_message
|
33
|
+
@too_short = opts[:too_short] || default_too_short_message
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
def full_too_short
|
38
|
+
too_short ? compose_full_message(too_short) : nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_too_long
|
42
|
+
too_long ? compose_full_message(too_long) : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
37
47
|
def to_a
|
38
48
|
super + [self.in.try(:sort), within.try(:sort), is.to_s, maximum.to_s, minimum.to_s, too_short.to_s, too_long.to_s]
|
39
49
|
end
|
40
50
|
|
51
|
+
def default_message
|
52
|
+
'is the wrong length'
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_too_short_message
|
56
|
+
minimum ? 'is too short' : nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_too_long_message
|
60
|
+
maximum ? 'is too long' : nil
|
61
|
+
end
|
62
|
+
|
41
63
|
private
|
42
64
|
|
43
65
|
def in_within_is_maximum_minimum_allowance
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mv-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valeriy Prokopchuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- LICENSE.txt
|
177
177
|
- README.md
|
178
178
|
- lib/mv-core.rb
|
179
|
+
- lib/mv/core/active_record/base_decorator.rb
|
179
180
|
- lib/mv/core/active_record/connection_adapters/abstract_adapter_decorator.rb
|
180
181
|
- lib/mv/core/active_record/connection_adapters/table_decorator.rb
|
181
182
|
- lib/mv/core/active_record/connection_adapters/table_definition_decorator.rb
|
@@ -224,6 +225,14 @@ files:
|
|
224
225
|
- lib/mv/core/services/synchronize_constraints.rb
|
225
226
|
- lib/mv/core/services/uninstall.rb
|
226
227
|
- lib/mv/core/validation/absence.rb
|
228
|
+
- lib/mv/core/validation/active_model_presenter/absence.rb
|
229
|
+
- lib/mv/core/validation/active_model_presenter/base.rb
|
230
|
+
- lib/mv/core/validation/active_model_presenter/exclusion.rb
|
231
|
+
- lib/mv/core/validation/active_model_presenter/factory.rb
|
232
|
+
- lib/mv/core/validation/active_model_presenter/inclusion.rb
|
233
|
+
- lib/mv/core/validation/active_model_presenter/length.rb
|
234
|
+
- lib/mv/core/validation/active_model_presenter/presence.rb
|
235
|
+
- lib/mv/core/validation/active_model_presenter/uniqueness.rb
|
227
236
|
- lib/mv/core/validation/base.rb
|
228
237
|
- lib/mv/core/validation/builder/absence.rb
|
229
238
|
- lib/mv/core/validation/builder/base.rb
|
@@ -256,7 +265,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
256
265
|
requirements:
|
257
266
|
- - '>='
|
258
267
|
- !ruby/object:Gem::Version
|
259
|
-
version: '0'
|
268
|
+
version: '2.0'
|
260
269
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
261
270
|
requirements:
|
262
271
|
- - '>='
|