store_model 0.5.1 → 0.5.2
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 +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
|