u-attributes 1.2.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,7 @@ module Micro::Attributes
7
7
  base.class_eval(<<-RUBY)
8
8
  def initialize(arg)
9
9
  self.attributes = arg
10
+ __call_after_micro_attribute
10
11
  end
11
12
  RUBY
12
13
  end
@@ -18,6 +19,10 @@ module Micro::Attributes
18
19
  def with_attributes(arg)
19
20
  self.class.new(attributes.merge(arg))
20
21
  end
22
+
23
+ private
24
+
25
+ def __call_after_micro_attribute; end
21
26
  end
22
27
  end
23
28
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro::Attributes
4
+ module Features
5
+ module Initialize
6
+ module Strict
7
+ module ClassMethods
8
+ def attributes_are_all_required?
9
+ true
10
+ end
11
+ end
12
+
13
+ def self.included(base)
14
+ base.send(:extend, ClassMethods)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -3,8 +3,31 @@
3
3
  module Micro
4
4
  module Attributes
5
5
  module Macros
6
- def __attributes_data
7
- @__attributes_data ||= {}
6
+ def attributes_are_all_required?
7
+ false
8
+ end
9
+
10
+ # NOTE: can't be renamed! It is used by u-case v4.
11
+ def __attributes_data__
12
+ @__attributes_data__ ||= {}
13
+ end
14
+
15
+ def __attributes_required__
16
+ @__attributes_required__ ||= Set.new
17
+ end
18
+
19
+ def __attributes_required_add(name, is_required, hasnt_default)
20
+ if is_required || (attributes_are_all_required? && hasnt_default)
21
+ __attributes_required__.add(name)
22
+ end
23
+
24
+ nil
25
+ end
26
+
27
+ def __attributes_data_to_assign(name, options)
28
+ hasnt_default = !options.key?(:default)
29
+
30
+ hasnt_default ? __attributes_required_add(name, options[:required], hasnt_default) : options[:default]
8
31
  end
9
32
 
10
33
  def __attributes
@@ -13,58 +36,69 @@ module Micro
13
36
 
14
37
  def __attribute_reader(name)
15
38
  __attributes.add(name)
39
+
16
40
  attr_reader(name)
17
41
  end
18
42
 
19
- def __attribute_set(key, value, can_overwrite)
43
+ def __attribute_assign(key, can_overwrite, options)
20
44
  name = key.to_s
21
45
  has_attribute = attribute?(name)
46
+
22
47
  __attribute_reader(name) unless has_attribute
23
- __attributes_data[name] = value if can_overwrite || !has_attribute
24
- end
25
48
 
26
- def __attributes_def(arg, can_overwrite)
27
- return __attribute_set(arg, nil, can_overwrite) unless arg.is_a?(::Hash)
28
- arg.each { |key, val| __attribute_set(key, val, can_overwrite) }
49
+ __attributes_data__[name] = __attributes_data_to_assign(name, options) if can_overwrite || !has_attribute
50
+
51
+ __call_after_attribute_assign__(name, options)
29
52
  end
30
53
 
31
- def __attributes_set(args, can_overwrite)
32
- args.flatten.each { |arg| __attributes_def(arg, can_overwrite) }
54
+ def __call_after_attribute_assign__(attr_name, options); end
55
+
56
+ # NOTE: can't be renamed! It is used by u-case v4.
57
+ def __attributes_set_after_inherit__(arg)
58
+ arg.each do |key, val|
59
+ __attribute_assign(key, true, val ? { default: val } : {})
60
+ end
33
61
  end
34
62
 
35
63
  def attribute?(name)
36
64
  __attributes.member?(name.to_s)
37
65
  end
38
66
 
39
- def attribute(name, value=nil)
40
- __attribute_set(name, value, false)
67
+ def attribute(name, options = Kind::Empty::HASH)
68
+ __attribute_assign(name, false, options)
41
69
  end
42
70
 
43
71
  def attributes(*args)
44
72
  return __attributes.to_a if args.empty?
45
- __attributes_set(args, can_overwrite: false)
46
- end
47
73
 
48
- def attributes_data(arg)
49
- __attributes_data.merge(AttributesUtils.stringify_hash_keys!(arg))
74
+ args.flatten!
75
+
76
+ options =
77
+ args.size > 1 && args.last.is_a?(::Hash) ? args.pop : Kind::Empty::HASH
78
+
79
+ args.each do |arg|
80
+ if arg.is_a?(String) || arg.is_a?(Symbol)
81
+ __attribute_assign(arg, false, options)
82
+ else
83
+ raise Kind::Error.new('String/Symbol'.freeze, arg)
84
+ end
85
+ end
50
86
  end
51
87
 
88
+ # NOTE: can't be renamed! It is used by u-case v4.
52
89
  module ForSubclasses
53
90
  WRONG_NUMBER_OF_ARGS = 'wrong number of arguments (given 0, expected 1 or more)'.freeze
54
91
 
55
- def attribute!(name, value=nil)
56
- __attribute_set(name, value, true)
57
- end
58
-
59
- def attributes!(*args)
60
- return __attributes_set(args, can_overwrite: true) unless args.empty?
61
- raise ArgumentError, WRONG_NUMBER_OF_ARGS
92
+ def attribute!(name, options = Kind::Empty::HASH)
93
+ __attribute_assign(name, true, options)
62
94
  end
63
95
 
64
96
  private_constant :WRONG_NUMBER_OF_ARGS
65
97
  end
98
+
66
99
  private_constant :ForSubclasses
67
100
  end
101
+
68
102
  private_constant :Macros
69
103
  end
70
104
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro::Attributes
4
+ module Utils
5
+ module Hashes
6
+ def self.stringify_keys(arg)
7
+ hash = Kind::Of.(::Hash, arg)
8
+
9
+ return hash if hash.empty?
10
+ return hash.transform_keys(&:to_s) if hash.respond_to?(:transform_keys)
11
+
12
+ hash.each_with_object({}) { |(key, val), memo| memo[key.to_s] = val }
13
+ end
14
+
15
+ def self.get(hash, key)
16
+ value = hash[key.to_s]
17
+
18
+ value.nil? ? hash[key.to_sym] : value
19
+ end
20
+ end
21
+
22
+ module ExtractAttribute
23
+ def self.call(object, key:)
24
+ return object.public_send(key) if object.respond_to?(key)
25
+
26
+ Hashes.get(object, key) if object.respond_to?(:[])
27
+ end
28
+
29
+ def self.from(object, keys:)
30
+ Kind::Of.(::Array, keys).each_with_object({}) do |key, memo|
31
+ memo[key] = call(object, key: key)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  module Attributes
5
- VERSION = '1.2.0'.freeze
5
+ VERSION = '2.2.0'.freeze
6
6
  end
7
7
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'micro/attributes/features/diff'
4
4
  require 'micro/attributes/features/initialize'
5
+ require 'micro/attributes/features/initialize/strict'
5
6
  require 'micro/attributes/features/activemodel_validations'
6
- require 'micro/attributes/features/strict_initialize'
7
7
 
8
8
  module Micro
9
9
  module Attributes
@@ -27,7 +27,7 @@ module Micro
27
27
 
28
28
  module ActiveModelValidations
29
29
  def self.included(base)
30
- base.send(:include, ::Micro::Attributes)
30
+ base.send(:include, Initialize)
31
31
  base.send(:include, ::Micro::Attributes::Features::ActiveModelValidations)
32
32
  end
33
33
  end
@@ -35,7 +35,7 @@ module Micro
35
35
  module StrictInitialize
36
36
  def self.included(base)
37
37
  base.send(:include, Initialize)
38
- base.send(:include, ::Micro::Attributes::Features::StrictInitialize)
38
+ base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
39
39
  end
40
40
  end
41
41
 
@@ -53,7 +53,7 @@ module Micro
53
53
  module DiffAndStrictInitialize
54
54
  def self.included(base)
55
55
  base.send(:include, DiffAndInitialize)
56
- base.send(:include, ::Micro::Attributes::Features::StrictInitialize)
56
+ base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
57
57
  end
58
58
  end
59
59
 
@@ -76,7 +76,7 @@ module Micro
76
76
  module ActiveModelValidationsAndStrictInitialize
77
77
  def self.included(base)
78
78
  base.send(:include, ActiveModelValidationsAndInitialize)
79
- base.send(:include, ::Micro::Attributes::Features::StrictInitialize)
79
+ base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
80
80
  end
81
81
  end
82
82
 
@@ -92,7 +92,7 @@ module Micro
92
92
  module ActiveModelValidationsAndDiffAndStrictInitialize
93
93
  def self.included(base)
94
94
  base.send(:include, ActiveModelValidationsAndDiffAndInitialize)
95
- base.send(:include, ::Micro::Attributes::Features::StrictInitialize)
95
+ base.send(:include, ::Micro::Attributes::Features::Initialize::Strict)
96
96
  end
97
97
  end
98
98
  end
@@ -1,28 +1,35 @@
1
1
 
2
- lib = File.expand_path("../lib", __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "micro/attributes/version"
4
+ require 'micro/attributes/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "u-attributes"
7
+ spec.name = 'u-attributes'
8
8
  spec.version = Micro::Attributes::VERSION
9
- spec.authors = ["Rodrigo Serradura"]
10
- spec.email = ["rodrigo.serradura@gmail.com"]
9
+ spec.authors = ['Rodrigo Serradura']
10
+ spec.email = ['rodrigo.serradura@gmail.com']
11
11
 
12
- spec.summary = %q{Define read-only attributes}
13
- spec.description = %q{This gem allows defining read-only attributes, that is, your objects will have only getters to access their attributes data.}
14
- spec.homepage = "https://github.com/serradura/u-attributes"
15
- spec.license = "MIT"
12
+ spec.summary = %q{Create "immutable" objects. No setters, just getters!}
13
+ spec.description =
14
+ "This gem allows you to define \"immutable\" objects, and your objects will have only getters and no setters. "\
15
+ "So, if you change some object attribute, you will have a new object instance. " \
16
+ "That is, you transform the object instead of modifying it."
17
+ spec.homepage = 'https://github.com/serradura/u-attributes'
18
+ spec.license = 'MIT'
16
19
 
17
20
  # Specify which files should be added to the gem when it is released.
18
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
22
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
24
  end
22
- spec.bindir = "exe"
25
+ spec.bindir = 'exe'
23
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
- spec.require_paths = ["lib"]
27
+ spec.require_paths = ['lib']
25
28
 
26
29
  spec.required_ruby_version = '>= 2.2.0'
27
- spec.add_development_dependency "rake", "~> 10.0"
30
+
31
+ spec.add_runtime_dependency 'kind', '>= 3.0', '< 5.0'
32
+
33
+ spec.add_development_dependency 'bundler'
34
+ spec.add_development_dependency 'rake', '~> 13.0'
28
35
  end
metadata CHANGED
@@ -1,31 +1,67 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-08 00:00:00.000000000 Z
11
+ date: 2020-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kind
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
13
47
  - !ruby/object:Gem::Dependency
14
48
  name: rake
15
49
  requirement: !ruby/object:Gem::Requirement
16
50
  requirements:
17
51
  - - "~>"
18
52
  - !ruby/object:Gem::Version
19
- version: '10.0'
53
+ version: '13.0'
20
54
  type: :development
21
55
  prerelease: false
22
56
  version_requirements: !ruby/object:Gem::Requirement
23
57
  requirements:
24
58
  - - "~>"
25
59
  - !ruby/object:Gem::Version
26
- version: '10.0'
27
- description: This gem allows defining read-only attributes, that is, your objects
28
- will have only getters to access their attributes data.
60
+ version: '13.0'
61
+ description: This gem allows you to define "immutable" objects, and your objects will
62
+ have only getters and no setters. So, if you change some object attribute, you will
63
+ have a new object instance. That is, you transform the object instead of modifying
64
+ it.
29
65
  email:
30
66
  - rodrigo.serradura@gmail.com
31
67
  executables: []
@@ -37,20 +73,21 @@ files:
37
73
  - ".travis.yml"
38
74
  - CODE_OF_CONDUCT.md
39
75
  - Gemfile
40
- - Gemfile.lock
41
76
  - LICENSE.txt
42
77
  - README.md
43
78
  - Rakefile
79
+ - assets/u-attributes_logo_v1.png
44
80
  - bin/console
45
81
  - bin/setup
46
82
  - lib/micro/attributes.rb
47
- - lib/micro/attributes/attributes_utils.rb
83
+ - lib/micro/attributes/diff.rb
48
84
  - lib/micro/attributes/features.rb
49
85
  - lib/micro/attributes/features/activemodel_validations.rb
50
86
  - lib/micro/attributes/features/diff.rb
51
87
  - lib/micro/attributes/features/initialize.rb
52
- - lib/micro/attributes/features/strict_initialize.rb
88
+ - lib/micro/attributes/features/initialize/strict.rb
53
89
  - lib/micro/attributes/macros.rb
90
+ - lib/micro/attributes/utils.rb
54
91
  - lib/micro/attributes/version.rb
55
92
  - lib/micro/attributes/with.rb
56
93
  - lib/u-attributes.rb
@@ -75,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
112
  - !ruby/object:Gem::Version
76
113
  version: '0'
77
114
  requirements: []
78
- rubygems_version: 3.0.3
115
+ rubygems_version: 3.0.6
79
116
  signing_key:
80
117
  specification_version: 4
81
- summary: Define read-only attributes
118
+ summary: Create "immutable" objects. No setters, just getters!
82
119
  test_files: []
@@ -1,29 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- u-attributes (1.2.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- docile (1.3.2)
10
- json (2.2.0)
11
- minitest (5.11.3)
12
- rake (10.5.0)
13
- simplecov (0.17.0)
14
- docile (~> 1.1)
15
- json (>= 1.8, < 3)
16
- simplecov-html (~> 0.10.0)
17
- simplecov-html (0.10.2)
18
-
19
- PLATFORMS
20
- ruby
21
-
22
- DEPENDENCIES
23
- minitest (~> 5.0)
24
- rake (~> 10.0)
25
- simplecov
26
- u-attributes!
27
-
28
- BUNDLED WITH
29
- 1.17.3