store_model 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/active_model/validations/store_model_validator.rb +8 -0
- data/lib/store_model.rb +1 -1
- data/lib/store_model/combine_errors_strategies.rb +6 -1
- data/lib/store_model/combine_errors_strategies/mark_invalid_error_strategy.rb +7 -0
- data/lib/store_model/combine_errors_strategies/merge_error_strategy.rb +8 -0
- data/lib/store_model/configuration.rb +3 -5
- data/lib/store_model/enum.rb +6 -0
- data/lib/store_model/model.rb +34 -3
- data/lib/store_model/nested_attributes.rb +6 -2
- data/lib/store_model/type_builders.rb +5 -0
- data/lib/store_model/types.rb +1 -0
- data/lib/store_model/types/array_type.rb +27 -0
- data/lib/store_model/types/enum_type.rb +14 -0
- data/lib/store_model/types/json_type.rb +26 -0
- data/lib/store_model/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ddf27da9ed2536f94b6363448b5198695e8c15113b94e4e160a10980a8709532
|
4
|
+
data.tar.gz: f508d45e6a30c2634a89fdbd8204643aa597f1c879958314bb0c83b4fe3fd27f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fccc4d5dee04b782758ada583a9a840b585805786869912a1d82e50a8df5dcfb682afc97b1dffe45961640a095395f1da4f3b27c0e94afeddc59de5a218c658e
|
7
|
+
data.tar.gz: ad0e9c6f11accc117b45a9647d525ad9a19acc47704d22261129e46ec648461b77585e3d4ff828ad3a00b46bf3b6968789af97a2ac8e1789d8c965c9da034c98
|
data/README.md
CHANGED
@@ -5,7 +5,15 @@ require "store_model/combine_errors_strategies"
|
|
5
5
|
|
6
6
|
module ActiveModel
|
7
7
|
module Validations
|
8
|
+
# +StoreModelValidator+ is a subclass of ActiveModel::EachValidator for
|
9
|
+
# checking StoreModel::Model attributes.
|
8
10
|
class StoreModelValidator < ActiveModel::EachValidator
|
11
|
+
# Validates _json_ attribute using the configured strategy or
|
12
|
+
# invalidates _array_ attribute when at least one element is invalid.
|
13
|
+
#
|
14
|
+
# @param record [ApplicationRecord] object to validate
|
15
|
+
# @param attribute [String] name of the validated attribute
|
16
|
+
# @param value [Object] value of the validated attribute
|
9
17
|
def validate_each(record, attribute, value)
|
10
18
|
if value.nil?
|
11
19
|
record.errors.add(attribute, :blank)
|
data/lib/store_model.rb
CHANGED
@@ -4,10 +4,15 @@ require "store_model/combine_errors_strategies/mark_invalid_error_strategy"
|
|
4
4
|
require "store_model/combine_errors_strategies/merge_error_strategy"
|
5
5
|
|
6
6
|
module StoreModel
|
7
|
+
# Module with built-in strategies for combining errors.
|
7
8
|
module CombineErrorsStrategies
|
8
9
|
module_function
|
9
10
|
|
10
|
-
# Finds a strategy based on options and global config
|
11
|
+
# Finds a strategy based on +options+ and global config.
|
12
|
+
#
|
13
|
+
# @param options [Hash]
|
14
|
+
#
|
15
|
+
# @return [Object] strategy
|
11
16
|
def configure(options)
|
12
17
|
configured_strategy = options[:merge_errors] || StoreModel.config.merge_errors
|
13
18
|
|
@@ -2,7 +2,14 @@
|
|
2
2
|
|
3
3
|
module StoreModel
|
4
4
|
module CombineErrorsStrategies
|
5
|
+
# +MarkInvalidErrorStrategy+ marks attribute invalid in the parent record.
|
5
6
|
class MarkInvalidErrorStrategy
|
7
|
+
# Invalidates +attribute+ in the parent record.
|
8
|
+
#
|
9
|
+
# @param attribute [String] name of the validated attribute
|
10
|
+
# @param base_errors [ActiveModel::Errors] errors object of the parent record
|
11
|
+
# @param _store_model_errors [ActiveModel::Errors] errors object of the
|
12
|
+
# StoreModel::Model attribute
|
6
13
|
def call(attribute, base_errors, _store_model_errors)
|
7
14
|
base_errors.add(attribute, :invalid)
|
8
15
|
end
|
@@ -2,7 +2,15 @@
|
|
2
2
|
|
3
3
|
module StoreModel
|
4
4
|
module CombineErrorsStrategies
|
5
|
+
# +MergeErrorStrategy+ copies errors from the StoreModel::Model to the parent
|
6
|
+
# record (for Rails < 6.1) or marks the attribute invalid (for Rails >= 6.1).
|
5
7
|
class MergeErrorStrategy
|
8
|
+
# Merges errors on +attribute+ from the child model with parent errors.
|
9
|
+
#
|
10
|
+
# @param _attribute [String] name of the validated attribute
|
11
|
+
# @param base_errors [ActiveModel::Errors] errors object of the parent record
|
12
|
+
# @param store_model_errors [ActiveModel::Errors] errors object of the StoreModel::Model
|
13
|
+
# attribute
|
6
14
|
def call(_attribute, base_errors, store_model_errors)
|
7
15
|
if Rails::VERSION::MAJOR < 6 || Rails::VERSION::MAJOR == 6 && Rails::VERSION::MINOR.zero?
|
8
16
|
base_errors.copy!(store_model_errors)
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StoreModel
|
4
|
-
# StoreModel configuration
|
5
|
-
#
|
6
|
-
# - `merge_errors` - set up to `true` to merge errors or specify your
|
7
|
-
# own strategy
|
8
|
-
#
|
4
|
+
# StoreModel configuration.
|
9
5
|
class Configuration
|
6
|
+
# Controls usage of MergeErrorStrategy
|
7
|
+
# @return [Boolean]
|
10
8
|
attr_accessor :merge_errors
|
11
9
|
end
|
12
10
|
end
|
data/lib/store_model/enum.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StoreModel
|
4
|
+
# Allows defining Rails-like enums
|
4
5
|
module Enum
|
6
|
+
# Defines new enum
|
7
|
+
#
|
8
|
+
# @param name [String] name of the enum to define
|
9
|
+
# @param values [Object]
|
10
|
+
# @param kwargs [Object]
|
5
11
|
def enum(name, values = nil, **kwargs)
|
6
12
|
values ||= kwargs[:in] || kwargs
|
7
13
|
|
data/lib/store_model/model.rb
CHANGED
@@ -6,8 +6,9 @@ require "store_model/type_builders"
|
|
6
6
|
require "store_model/nested_attributes"
|
7
7
|
|
8
8
|
module StoreModel
|
9
|
+
# When included into class configures it to handle JSON column
|
9
10
|
module Model
|
10
|
-
def self.included(base)
|
11
|
+
def self.included(base) # :nodoc:
|
11
12
|
base.include ActiveModel::Model
|
12
13
|
base.include ActiveModel::Attributes
|
13
14
|
base.include StoreModel::NestedAttributes
|
@@ -16,21 +17,37 @@ module StoreModel
|
|
16
17
|
base.extend StoreModel::TypeBuilders
|
17
18
|
end
|
18
19
|
|
20
|
+
# Returns a hash representing the model. Some configuration can be
|
21
|
+
# passed through +options+.
|
22
|
+
#
|
23
|
+
# @param options [Hash]
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
19
26
|
def as_json(options = {})
|
20
27
|
attributes.with_indifferent_access.as_json(options)
|
21
28
|
end
|
22
29
|
|
30
|
+
# Compares two StoreModel::Model instances
|
31
|
+
#
|
32
|
+
# @param other [StoreModel::Model]
|
33
|
+
#
|
34
|
+
# @return [Boolean]
|
23
35
|
def ==(other)
|
24
36
|
return super unless other.is_a?(self.class)
|
25
37
|
|
26
|
-
attributes.all? { |name, value| value == other.
|
38
|
+
attributes.all? { |name, value| value == other.attributes[name] }
|
27
39
|
end
|
28
40
|
|
29
|
-
# Allows to call :presence validation on the association itself
|
41
|
+
# Allows to call :presence validation on the association itself.
|
42
|
+
#
|
43
|
+
# @return [Boolean]
|
30
44
|
def blank?
|
31
45
|
attributes.values.all?(&:blank?)
|
32
46
|
end
|
33
47
|
|
48
|
+
# String representation of the object.
|
49
|
+
#
|
50
|
+
# @return [String]
|
34
51
|
def inspect
|
35
52
|
attribute_string = attributes.map { |name, value| "#{name}: #{value || 'nil'}" }.join(", ")
|
36
53
|
"#<#{self.class.name} #{attribute_string}>"
|
@@ -38,17 +55,31 @@ module StoreModel
|
|
38
55
|
|
39
56
|
delegate :attribute_types, to: :class
|
40
57
|
|
58
|
+
# Returns the type of the attribute with the given name
|
59
|
+
#
|
60
|
+
# @param attr_name [String] name of the attribute
|
61
|
+
#
|
62
|
+
# @return [ActiveModel::Type::Value]
|
41
63
|
def type_for_attribute(attr_name)
|
42
64
|
attr_name = attr_name.to_s
|
43
65
|
attribute_types[attr_name]
|
44
66
|
end
|
45
67
|
|
68
|
+
# Checks if the attribute with a given name is defined
|
69
|
+
#
|
70
|
+
# @param attr_name [String] name of the attribute
|
71
|
+
#
|
72
|
+
# @return [Boolean]
|
46
73
|
# rubocop:disable Naming/PredicateName
|
47
74
|
def has_attribute?(attr_name)
|
48
75
|
attribute_types.key?(attr_name.to_s)
|
49
76
|
end
|
50
77
|
# rubocop:enable Naming/PredicateName
|
51
78
|
|
79
|
+
# Contains a hash of attributes which are not defined but exist in the
|
80
|
+
# underlying JSON data
|
81
|
+
#
|
82
|
+
# @return [Hash]
|
52
83
|
def unknown_attributes
|
53
84
|
@unknown_attributes ||= {}
|
54
85
|
end
|
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StoreModel
|
4
|
+
# Contains methods for working with nested StoreModel::Model attributes.
|
4
5
|
module NestedAttributes
|
5
|
-
def self.included(base)
|
6
|
+
def self.included(base) # :nodoc:
|
6
7
|
base.extend ClassMethods
|
7
8
|
end
|
8
9
|
|
9
|
-
module ClassMethods
|
10
|
+
module ClassMethods # :nodoc:
|
11
|
+
# Enables handling of nested StoreModel::Model attributes
|
12
|
+
#
|
13
|
+
# @param associations [Array] list of associations to define attributes
|
10
14
|
def accepts_nested_attributes_for(*associations)
|
11
15
|
associations.each do |association|
|
12
16
|
case attribute_types[association.to_s]
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module StoreModel
|
4
|
+
# Contains methods for converting StoreModel::Model to ActiveModel::Type::Value.
|
4
5
|
module TypeBuilders
|
6
|
+
# Converts StoreModel::Model to Types::JsonType
|
7
|
+
# @return [Types::JsonType]
|
5
8
|
def to_type
|
6
9
|
Types::JsonType.new(self)
|
7
10
|
end
|
8
11
|
|
12
|
+
# Converts StoreModel::Model to Types::ArrayType
|
13
|
+
# @return [Types::ArrayType]
|
9
14
|
def to_array_type
|
10
15
|
Types::ArrayType.new(self)
|
11
16
|
end
|
data/lib/store_model/types.rb
CHANGED
@@ -4,15 +4,30 @@ require "active_model"
|
|
4
4
|
|
5
5
|
module StoreModel
|
6
6
|
module Types
|
7
|
+
# Implements ActiveModel::Type::Value type for handling an array of
|
8
|
+
# StoreModel::Model
|
7
9
|
class ArrayType < ActiveModel::Type::Value
|
10
|
+
# Initializes type for model class
|
11
|
+
#
|
12
|
+
# @param model_klass [StoreModel::Model] model class to handle
|
13
|
+
#
|
14
|
+
# @return [StoreModel::Types::ArrayType]
|
8
15
|
def initialize(model_klass)
|
9
16
|
@model_klass = model_klass
|
10
17
|
end
|
11
18
|
|
19
|
+
# Returns type
|
20
|
+
#
|
21
|
+
# @return [Symbol]
|
12
22
|
def type
|
13
23
|
:array
|
14
24
|
end
|
15
25
|
|
26
|
+
# Casts +value+ from DB or user to StoreModel::Model instance
|
27
|
+
#
|
28
|
+
# @param value [Object] a value to cast
|
29
|
+
#
|
30
|
+
# @return StoreModel::Model
|
16
31
|
def cast_value(value)
|
17
32
|
case value
|
18
33
|
when String then decode_and_initialize(value)
|
@@ -24,6 +39,12 @@ module StoreModel
|
|
24
39
|
end
|
25
40
|
end
|
26
41
|
|
42
|
+
# Casts a value from the ruby type to a type that the database knows how
|
43
|
+
# to understand.
|
44
|
+
#
|
45
|
+
# @param value [Object] value to serialize
|
46
|
+
#
|
47
|
+
# @return [String] serialized value
|
27
48
|
def serialize(value)
|
28
49
|
case value
|
29
50
|
when Array
|
@@ -33,6 +54,12 @@ module StoreModel
|
|
33
54
|
end
|
34
55
|
end
|
35
56
|
|
57
|
+
# Determines whether the mutable value has been modified since it was read
|
58
|
+
#
|
59
|
+
# @param raw_old_value [Object] old value
|
60
|
+
# @param new_value [Object] new value
|
61
|
+
#
|
62
|
+
# @return [Boolean]
|
36
63
|
def changed_in_place?(raw_old_value, new_value)
|
37
64
|
cast_value(raw_old_value) != new_value
|
38
65
|
end
|
@@ -4,15 +4,29 @@ require "active_model"
|
|
4
4
|
|
5
5
|
module StoreModel
|
6
6
|
module Types
|
7
|
+
# Implements ActiveModel::Type::Value type for handling Rails-like enums
|
7
8
|
class EnumType < ActiveModel::Type::Value
|
9
|
+
# Initializes type for mapping
|
10
|
+
#
|
11
|
+
# @param mapping [Hash] mapping for enum values
|
12
|
+
#
|
13
|
+
# @return [StoreModel::Types::EnumType]
|
8
14
|
def initialize(mapping)
|
9
15
|
@mapping = mapping
|
10
16
|
end
|
11
17
|
|
18
|
+
# Returns type
|
19
|
+
#
|
20
|
+
# @return [Symbol]
|
12
21
|
def type
|
13
22
|
:integer
|
14
23
|
end
|
15
24
|
|
25
|
+
# Casts +value+ from DB or user to StoreModel::Model instance
|
26
|
+
#
|
27
|
+
# @param value [Object] a value to cast
|
28
|
+
#
|
29
|
+
# @return StoreModel::Model
|
16
30
|
def cast_value(value)
|
17
31
|
return if value.blank?
|
18
32
|
|
@@ -4,15 +4,29 @@ require "active_model"
|
|
4
4
|
|
5
5
|
module StoreModel
|
6
6
|
module Types
|
7
|
+
# Implements ActiveModel::Type::Value type for handling an instance of StoreModel::Model
|
7
8
|
class JsonType < ActiveModel::Type::Value
|
9
|
+
# Initializes type for model class
|
10
|
+
#
|
11
|
+
# @param model_klass [StoreModel::Model] model class to handle
|
12
|
+
#
|
13
|
+
# @return [StoreModel::Types::JsonType]
|
8
14
|
def initialize(model_klass)
|
9
15
|
@model_klass = model_klass
|
10
16
|
end
|
11
17
|
|
18
|
+
# Returns type
|
19
|
+
#
|
20
|
+
# @return [Symbol]
|
12
21
|
def type
|
13
22
|
:json
|
14
23
|
end
|
15
24
|
|
25
|
+
# Casts +value+ from DB or user to StoreModel::Model instance
|
26
|
+
#
|
27
|
+
# @param value [Object] a value to cast
|
28
|
+
#
|
29
|
+
# @return StoreModel::Model
|
16
30
|
def cast_value(value)
|
17
31
|
case value
|
18
32
|
when String then decode_and_initialize(value)
|
@@ -24,6 +38,12 @@ module StoreModel
|
|
24
38
|
handle_unknown_attribute(value, e)
|
25
39
|
end
|
26
40
|
|
41
|
+
# Casts a value from the ruby type to a type that the database knows how
|
42
|
+
# to understand.
|
43
|
+
#
|
44
|
+
# @param value [Object] value to serialize
|
45
|
+
#
|
46
|
+
# @return [String] serialized value
|
27
47
|
def serialize(value)
|
28
48
|
case value
|
29
49
|
when Hash, @model_klass
|
@@ -33,6 +53,12 @@ module StoreModel
|
|
33
53
|
end
|
34
54
|
end
|
35
55
|
|
56
|
+
# Determines whether the mutable value has been modified since it was read
|
57
|
+
#
|
58
|
+
# @param raw_old_value [Object] old value
|
59
|
+
# @param new_value [Object] new value
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
36
62
|
def changed_in_place?(raw_old_value, new_value)
|
37
63
|
cast_value(raw_old_value) != new_value
|
38
64
|
end
|
data/lib/store_model/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: store_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DmitryTsepelev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|