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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24ffb629e586415bc6671bc83c69ab96f61c1133
4
- data.tar.gz: 1a7d2b792298becc6cba981959ad868887921264
3
+ metadata.gz: ab1d009f28ad7d42d5c3bd4aa052c3bac79a25dd
4
+ data.tar.gz: 3c1db440ab887e8f16efeb8f43ead8fde721ce3d
5
5
  SHA512:
6
- metadata.gz: 9d38da1fab2a62805a97466da3c5ee6d43596d1ff207bf8fb4343983df89b56b524d6a83be938557a36a3b8df8e3e9266b4c92c05898961d376e82f839206074
7
- data.tar.gz: 20c0fcb064136a2bf20623b96c4137557f82e54b32b075f594b6a89c8779b047f206c4c2b7bdadc73734c6a3d797272d8b3afed80750e0643ae73f6e7ae82c47
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
- # Project goals
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
- Main goal of the project is to allow developer to express database constraints in a rdms - agnostic syntax that is similiar to validators in Rails.
27
+ # Why `Migration Validators`
13
28
 
14
- # mv-core
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
- mv-core is a set of core classes that are used everywhere across Migration Validators project gems.
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
- This gem is not intended to be installed directly and referenced from within the application. You should rather install appropriate driver.
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
- # Install
35
+ The goal of the `Migration Validators` project is to resolve those problems and make DB constraints management straightforward
21
36
 
22
- PostgreSQL:
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
- MySQL:
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
- SQLite:
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
- create_table do |t|
46
- t.string :str_column, validates: { uniqueness: :true,
47
- inclusion: { in: 1..3 }}
48
- t.column :column_name, :integer, validates: { exclusion: { in: [1,2,3]}}
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
- change_table do |t|
56
- t.change :str_column, :integer, validates: { exclusion: { in: [1,2,3] }}
57
- t.validates :column_name, inclusion: { in: 1..3 }
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
- Update validator definition:
62
-
63
- ```ruby
64
- validates :table_name, :str_column, exclusion: { in: [1,2,3] }
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
- Remove existing validators:
79
+ Update validation definition:
68
80
 
69
81
  ```ruby
70
- change_table do |t|
71
- t.change :str_column, :integer, validates: { exclusion: false }
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 constaint should be
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
- validates :table_name, :str_column, uniqueness: { as: :trigger }
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
- validates :table_name, :str_column, uniqueness: { as: :check }
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
- validates :table_name, :str_column, uniqueness: { on: :create }
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
- validates :table_name, :str_column, uniqueness: { on: :update }
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
- validates :table_name, :str_column,
109
- custom: { statement: 'LENGTH(TRIM({str_column})) > 10',
110
- on: :update }
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
- validates :table_name, :str_column, uniqueness: true, presence: true
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
- validates :table_name, :str_column, length: 1..3
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
- validates :table_name, :str_column, custom: 'LENGTH(TRIM({str_column})) > 10'
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
- # Maintenance tasks
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
- ## Contributing to mv-core
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.
@@ -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
@@ -22,6 +22,10 @@ module Mv
22
22
  true
23
23
  end
24
24
 
25
+ def default_message
26
+ 'must be blank'
27
+ end
28
+
25
29
  private
26
30
 
27
31
  def nil_and_blank_can_not_be_both_denied
@@ -0,0 +1,15 @@
1
+ require 'mv/core/validation/active_model_presenter/base'
2
+
3
+ module Mv
4
+ module Core
5
+ module Validation
6
+ module ActiveModelPresenter
7
+ class Absence < Base
8
+ def validation_name
9
+ :absence
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ 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
@@ -0,0 +1,15 @@
1
+ require 'mv/core/validation/active_model_presenter/base'
2
+
3
+ module Mv
4
+ module Core
5
+ module Validation
6
+ module ActiveModelPresenter
7
+ class Presence < Base
8
+ def validation_name
9
+ :presence
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'mv/core/validation/active_model_presenter/base'
2
+
3
+ module Mv
4
+ module Core
5
+ module Validation
6
+ module ActiveModelPresenter
7
+ class Uniqueness < Base
8
+ def validation_name
9
+ :uniqueness
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ 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(', ')})",
@@ -19,6 +19,12 @@ module Mv
19
19
  def to_a
20
20
  super + [statement.to_s]
21
21
  end
22
+
23
+ protected
24
+
25
+ def default_message
26
+ 'is invalid'
27
+ end
22
28
  end
23
29
  end
24
30
  end
@@ -23,6 +23,12 @@ module Mv
23
23
  prepared_in = self.in.is_a?(Range) ? [self.in.min, self.in.max] : self.in.try(:sort)
24
24
  super + [prepared_in]
25
25
  end
26
+
27
+ protected
28
+
29
+ def default_message
30
+ 'is reserved'
31
+ end
26
32
  end
27
33
  end
28
34
  end
@@ -23,6 +23,12 @@ module Mv
23
23
  prepared_in = self.in.is_a?(Range) ? [self.in.min, self.in.max] : self.in.try(:sort)
24
24
  super + [prepared_in]
25
25
  end
26
+
27
+ protected
28
+
29
+ def default_message
30
+ 'is not included in the list'
31
+ end
26
32
  end
27
33
  end
28
34
  end
@@ -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
@@ -12,6 +12,12 @@ module Mv
12
12
  super(table_name, column_name, opts == true ? {} : opts)
13
13
  end
14
14
 
15
+ protected
16
+
17
+ def default_message
18
+ "can't be blank"
19
+ end
20
+
15
21
  private
16
22
 
17
23
  def nil_and_blank_can_not_be_both_allowed
@@ -36,6 +36,10 @@ module Mv
36
36
  "idx_mv_#{table_name}_#{column_name}_uniq" if index?
37
37
  end
38
38
 
39
+ def default_message
40
+ 'is not unique'
41
+ end
42
+
39
43
  private
40
44
 
41
45
  def index?
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.1.0
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-22 00:00:00.000000000 Z
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
  - - '>='