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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e08694a9eb910d42bd5c9a1f6f2b23746494aad264315e8b7c1de863148fb72
4
- data.tar.gz: e5fd75336b9c22c9b75a5de967e2019e54bef594ff7d526fa56dc0ccdac9237e
3
+ metadata.gz: ddf27da9ed2536f94b6363448b5198695e8c15113b94e4e160a10980a8709532
4
+ data.tar.gz: f508d45e6a30c2634a89fdbd8204643aa597f1c879958314bb0c83b4fe3fd27f
5
5
  SHA512:
6
- metadata.gz: b229005093bd41076d547b093880954c060623ce2906b782e7e675ae5416b7f27b5876172d16d137d4be33a521449a196f30f170b946df174e4b0732ebad16a1
7
- data.tar.gz: 5add920a20c6b2f56121fe360c70f878de2ea194f7a0e5347168a5d9e4f72a7eed660d4966b8b4b0476c57fe90e99425da9b219abc59f7b487a91b21679bbddf
6
+ metadata.gz: fccc4d5dee04b782758ada583a9a840b585805786869912a1d82e50a8df5dcfb682afc97b1dffe45961640a095395f1da4f3b27c0e94afeddc59de5a218c658e
7
+ data.tar.gz: ad0e9c6f11accc117b45a9647d525ad9a19acc47704d22261129e46ec648461b77585e3d4ff828ad3a00b46bf3b6968789af97a2ac8e1789d8c965c9da034c98
data/README.md CHANGED
@@ -89,6 +89,7 @@ product.save
89
89
  * [Unknown attributes](./docs/unknown_attributes.md)
90
90
  3. [Array of stored models](./docs/array_of_stored_models.md)
91
91
  4. [Alternatives](./docs/alternatives.md)
92
+ 5. [Defining custom types](./docs/defining_custom_types.md)
92
93
 
93
94
  ## License
94
95
 
@@ -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)
@@ -4,7 +4,7 @@ require "store_model/model"
4
4
  require "store_model/configuration"
5
5
  require "active_model/validations/store_model_validator"
6
6
 
7
- module StoreModel
7
+ module StoreModel # :nodoc:
8
8
  class << self
9
9
  def config
10
10
  @config ||= Configuration.new
@@ -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
@@ -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
 
@@ -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.send(name) }
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
@@ -5,6 +5,7 @@ require "store_model/types/array_type"
5
5
  require "store_model/types/enum_type"
6
6
 
7
7
  module StoreModel
8
+ # Contains all custom types.
8
9
  module Types
9
10
  class CastError < StandardError; end
10
11
  end
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module StoreModel
4
- VERSION = "0.5.1"
3
+ module StoreModel # :nodoc:
4
+ VERSION = "0.5.2"
5
5
  end
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.1
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-06 00:00:00.000000000 Z
11
+ date: 2019-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails