shale-builder 0.4.1 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a79ea1df97f6d5d49af0d596144d931b5aacea98e142866d7e322497fbeaae5
4
- data.tar.gz: 59f671f470be89ed4854798843657160c87163de286a867be73c4832bb4a2df2
3
+ metadata.gz: febc908c436d767296b5869c0f83de5192ebd2dea56649a68840f951ca61210e
4
+ data.tar.gz: 921efc21393a6a01516dc0954efe6f87fe74326d51d1969c00e985f3f8ad9824
5
5
  SHA512:
6
- metadata.gz: f763a5973d2d15c2a2c314ae61ed61f7455724f624f38852f8cd4d174fe2bf12af7bee2eb37a847b5940f9779fa4ad2960eff6a99259c12d0445d16fb63b8775
7
- data.tar.gz: e872ffe315cec734fa77af67b1be80efded4b750194e66c2e41d069302b5dc18cc4bd0f3da2932528661cc2fa1d84ff90a08f3326c7052a65030987f5c4685eb
6
+ metadata.gz: 315da1873bcba3a08cbf4a6d405b975a8c9be51442726faab0e886138be48b50fa6bec7c5367064d1d0cc731af17ec0c10bbe9cfb04716a5b1d0712de46244a5
7
+ data.tar.gz: 54df3a9708bc1e327ecb7f85338a1420cca5b98d82b754acbecd03417541951472b9f2d005035abe5fe1217bfd5db10d3730a1966043c65956b3cdb83d080299
data/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] - 2025-10-15
9
+
10
+ [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.4.1...v0.5.0)
11
+
12
+ ### Changes
13
+ - Add `Shale::Builder::AssignedAttributes` module which grants a shale mapper class with the ability to record which attributes have been assigned
14
+ - Add `Shale::Builder::Value` which represents a value of a shale attribute.
15
+ - Add `Shale::Builder#attribute_values`, a method that returns an array of `Shale::Builder::Value` objects for each attribute.
16
+
8
17
  ## [0.4.1] - 2025-10-14
9
18
 
10
19
  [Diff](https://github.com/Verseth/ruby-shale-builder/compare/v0.4.0...v0.4.1)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shale-builder (0.4.1)
4
+ shale-builder (0.5.0)
5
5
  booleans (>= 0.1)
6
6
  shale (< 2.0)
7
7
  sorbet-runtime (> 0.5)
data/README.md CHANGED
@@ -263,6 +263,41 @@ obj.errors.messages #=> {cvv_code: ["can't be blank"], "amount.value": ["can't b
263
263
 
264
264
  You MUST include `ActiveModel::Validations` before `Shale::Builder::NestedValidations`.
265
265
 
266
+ ### Recording Assigned Attributes
267
+
268
+ There is an additional module `Shale::Builder::AssignedAttributes` that provides
269
+ support for recording which attributes have been assigned in a shale mapper object.
270
+
271
+ In order to load it do:
272
+
273
+ ```rb
274
+ require 'shale/builder/assigned_attributes'
275
+ ```
276
+
277
+ Then you can use it like so
278
+
279
+ ```rb
280
+ class AmountType < ::Shale::Mapper
281
+ include ::Shale::Builder
282
+ include ::Shale::Builder::AssignedAttributes
283
+
284
+ attribute :value, ::Shale::Type::Float
285
+ attribute :currency, ::Shale::Type::String
286
+ end
287
+
288
+ obj = AmountType.new
289
+ obj.assigned_attribute_names #=> #<Set: {}>
290
+
291
+ obj.value = 3
292
+ obj.assigned_attribute_names #=> #<Set: {:value}>
293
+ obj.assigned_attributes #=> [#<Shale::Attribute:0x000000011e959b50 @collection=false, @default=nil, @doc=nil, @name=:value, @setter="value=", @type=Shale::Type::Float>]
294
+ obj.assigned_values #=> [#<Shale::Builder::Value:0x000000011d693318 @attribute=#<Shale::Attribute:0x000000011e959b50 @collection=false, @default=nil, @doc=nil, @name=:value, @setter="value=", @type=Shale::Type::Float>, @value=3.0>]
295
+ ```
296
+
297
+ - `assigned_attribute_names` returns a set of attribute names
298
+ - `assigned_attributes` returns an array of attribute definitions
299
+ - `assigned_values` returns an array of `Shale::Builder::Value`, which contains the current value of an attribute and a reference to its definition
300
+
266
301
  ### Attribute aliases
267
302
 
268
303
  You can easily create aliases for attributes using `alias_attribute`
@@ -9,15 +9,15 @@ module Shale
9
9
 
10
10
  # Contains the documentation comment for the shale attribute
11
11
  # in a Ruby String.
12
- sig { returns(T.nilable(String)) }
12
+ #: String?
13
13
  attr_accessor :doc
14
14
 
15
15
  # Contains the documentation comment for the shale attribute
16
16
  # in a Ruby String.
17
- sig { returns(T.nilable(T::Array[Symbol])) }
17
+ #: Array[Symbol]?
18
18
  attr_accessor :aliases
19
19
 
20
- sig { returns(T::Array[Symbol]) }
20
+ #: -> Array[Symbol]
21
21
  def all_names
22
22
  names = [name]
23
23
  aliases = self.aliases
@@ -25,5 +25,12 @@ module Shale
25
25
 
26
26
  names + aliases
27
27
  end
28
+
29
+ # Returns `true` if the attribute is handled by a shale mapper.
30
+ #
31
+ #: -> bool
32
+ def mapper?
33
+ type.is_a?(Class) && type < Shale::Mapper
34
+ end
28
35
  end
29
36
  end
@@ -0,0 +1,94 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'shale'
5
+ require 'booleans'
6
+
7
+ module Shale
8
+ module Builder
9
+ # Include in a class that already includes `Shale::Builder` to add support
10
+ # for getting a list of attributes that have been assigned.
11
+ #
12
+ # @requires_ancestor: Object
13
+ module AssignedAttributes
14
+ extend T::Sig
15
+ extend T::Helpers
16
+
17
+ class << self
18
+ extend T::Sig
19
+
20
+ # Gets called after including this module in a module or class.
21
+ #: (Module mod) -> void
22
+ def included(mod)
23
+ mod.extend ClassMethods
24
+ AssignedAttributes.prepare_mod(mod)
25
+ end
26
+
27
+ # Prepares the received module or class
28
+ # for dynamic method definition.
29
+ #: (Module mod) -> void
30
+ def prepare_mod(mod)
31
+ assigned_attributes_methods_module = ::Module.new
32
+ mod.instance_variable_set :@assigned_attributes_methods_module, assigned_attributes_methods_module
33
+ mod.include assigned_attributes_methods_module
34
+ end
35
+ end
36
+
37
+ # @requires_ancestor: singleton(Shale::Mapper)
38
+ module ClassMethods
39
+ extend T::Sig
40
+
41
+ # Contains overridden getter methods for attributes
42
+ # with complex types (so that they accept a block for building)
43
+ #: Module
44
+ attr_reader :assigned_attributes_methods_module
45
+
46
+ #: (String | Symbol name, Class type, ?collection: bool, ?default: Proc?, ?doc: String?, **untyped kwargs) ?{ -> void } -> void
47
+ def attribute(name, type, collection: false, default: nil, doc: nil, **kwargs, &block)
48
+ super
49
+
50
+ @assigned_attributes_methods_module.class_eval <<~RUBY, __FILE__, __LINE__ + 1
51
+ def #{name}=(val)
52
+ super
53
+ return unless @__initialized
54
+
55
+ self.assigned_attribute_names << #{name.to_sym.inspect}
56
+ end
57
+ RUBY
58
+ end
59
+ end
60
+ mixes_in_class_methods ClassMethods
61
+
62
+ # Returns a set of names of assigned shale attributes.
63
+ #
64
+ #: -> Set[Symbol]
65
+ def assigned_attribute_names
66
+ @assigned_attribute_names ||= Set.new
67
+ end
68
+
69
+ # Returns an array of shale attributes
70
+ # that have been assigned.
71
+ #
72
+ #: -> Array[Shale::Attribute]
73
+ def assigned_attributes
74
+ klass = self.class #: as untyped
75
+ assigned_attribute_names.map do |name|
76
+ klass.attributes.fetch(name)
77
+ end
78
+ end
79
+
80
+ # Returns an array of shale values
81
+ # that have been assigned.
82
+ #
83
+ #: -> Array[Shale::Builder::Value]
84
+ def assigned_values
85
+ klass = self.class #: as untyped
86
+ assigned_attribute_names.map do |name|
87
+ attr = klass.attributes.fetch(name)
88
+ Shale::Builder::Value.new(attr, public_send(attr.name))
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -6,7 +6,7 @@ require 'booleans'
6
6
 
7
7
  module Shale
8
8
  module Builder
9
- # Include in a class tha already includes `Shale::Builder` to add support
9
+ # Include in a class that already includes `Shale::Builder` to add support
10
10
  # for nested ActiveModel validations.
11
11
  #
12
12
  # @requires_ancestor: Object
@@ -0,0 +1,30 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'shale'
5
+
6
+ module Shale
7
+ module Builder
8
+ # Represents a value of a particular shale attribute.
9
+ # Hold the value and a reference to the attribute definition.
10
+ class Value
11
+ extend T::Sig
12
+
13
+ # Shale attribute definition
14
+ #
15
+ #: Shale::Attribute
16
+ attr_reader :attribute
17
+
18
+ # Value of the attribute.
19
+ #
20
+ #: untyped
21
+ attr_reader :value
22
+
23
+ #: (Shale::Attribute, untyped) -> void
24
+ def initialize(attribute, value)
25
+ @attribute = attribute
26
+ @value = value
27
+ end
28
+ end
29
+ end
30
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Shale
4
4
  module Builder
5
- VERSION = '0.4.1'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
data/lib/shale/builder.rb CHANGED
@@ -39,6 +39,7 @@ module Shale
39
39
  # end
40
40
  # end
41
41
  #
42
+ # @requires_ancestor: Object
42
43
  module Builder
43
44
  extend T::Sig
44
45
  extend T::Helpers
@@ -47,7 +48,7 @@ module Shale
47
48
  extend T::Sig
48
49
 
49
50
  # Gets called after including this module in a module or class.
50
- sig { params(mod: Module).void }
51
+ #: (Module mod) -> void
51
52
  def included(mod)
52
53
  mod.extend ClassMethods
53
54
  Builder.prepare_mod(mod)
@@ -55,7 +56,7 @@ module Shale
55
56
 
56
57
  # Prepares the received module or class
57
58
  # for dynamic method definition.
58
- sig { params(mod: Module).void }
59
+ #: (Module mod) -> void
59
60
  def prepare_mod(mod)
60
61
  builder_methods_module = ::Module.new
61
62
  mod.instance_variable_set :@builder_methods_module, builder_methods_module
@@ -71,7 +72,7 @@ module Shale
71
72
  abstract!
72
73
  has_attached_class!
73
74
 
74
- sig { params(subclass: Class).void }
75
+ #: (Class subclass) -> void
75
76
  def inherited(subclass)
76
77
  super
77
78
  Builder.prepare_mod(subclass)
@@ -79,10 +80,10 @@ module Shale
79
80
 
80
81
  # Contains overridden getter methods for attributes
81
82
  # with complex types (so that they accept a block for building)
82
- sig { returns(Module) }
83
+ #: Module
83
84
  attr_reader :builder_methods_module
84
85
 
85
- sig { params(_block: T.proc.params(arg0: T.attached_class).void).returns(T.attached_class) }
86
+ #: { (instance arg0) -> void } -> instance
86
87
  def build(&_block)
87
88
  body = new
88
89
  yield(body)
@@ -96,17 +97,7 @@ module Shale
96
97
  sig { abstract.returns(T::Hash[Symbol, Shale::Attribute]) }
97
98
  def attributes; end
98
99
 
99
- sig do
100
- params(
101
- name: T.any(String, Symbol),
102
- type: Class,
103
- collection: T::Boolean,
104
- default: T.nilable(Proc),
105
- doc: T.nilable(String),
106
- kwargs: Object,
107
- block: T.nilable(T.proc.void),
108
- ).void
109
- end
100
+ #: ((String | Symbol) name, Class type, ?collection: bool, ?default: Proc?, ?doc: String?, **Object kwargs) ?{ -> void } -> void
110
101
  def attribute(name, type, collection: false, default: nil, doc: nil, **kwargs, &block)
111
102
  super(name, type, collection:, default:, **kwargs, &block)
112
103
  if (attr_def = attributes[name.to_sym])
@@ -141,7 +132,7 @@ module Shale
141
132
  end
142
133
 
143
134
  # Create an alias for the getter and setter of an attribute.
144
- sig { params(new_name: Symbol, old_name: Symbol).void }
135
+ #: (Symbol new_name, Symbol old_name) -> void
145
136
  def alias_attribute(new_name, old_name)
146
137
  attr = attributes.fetch(old_name)
147
138
  (attr.aliases ||= []) << new_name
@@ -160,5 +151,26 @@ module Shale
160
151
  end
161
152
  mixes_in_class_methods(ClassMethods)
162
153
 
154
+ def initialize(*args, **kwargs, &block)
155
+ super
156
+ @__initialized = true
157
+ end
158
+
159
+ #: bool?
160
+ attr_reader :__initialized
161
+
162
+ # Returns an array of shale values
163
+ # that have been assigned.
164
+ #
165
+ #: -> Array[Shale::Builder::Value]
166
+ def attribute_values
167
+ klass = self.class #: as untyped
168
+ klass.attributes.map do |name, attr|
169
+ Shale::Builder::Value.new(attr, public_send(name))
170
+ end
171
+ end
172
+
163
173
  end
164
174
  end
175
+
176
+ require_relative 'builder/value'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shale-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Drewniak
@@ -69,7 +69,9 @@ files:
69
69
  - Rakefile
70
70
  - lib/shale/attribute.rb
71
71
  - lib/shale/builder.rb
72
+ - lib/shale/builder/assigned_attributes.rb
72
73
  - lib/shale/builder/nested_validations.rb
74
+ - lib/shale/builder/value.rb
73
75
  - lib/shale/builder/version.rb
74
76
  - lib/shale/mapper.rbi
75
77
  - lib/tapioca/dsl/compilers/shale.rb