structure 1.1.1 → 1.2.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: bcf8086bf1877fd717dc7502032e3885d330b9f94121ccdf78c7284e2d5142d9
4
- data.tar.gz: c57b41a06c261f717dc00b3d4b97a2ff764b84fcfcbf4a478a53aaba6f60b646
3
+ metadata.gz: 6b08d68f313a052ecf51e5ddae25a9c01b2fa97f4d62faffd0886036f2143569
4
+ data.tar.gz: '0330855f5dbce7826cbdc2c845e719c81e6b1e60e17fcf5bc3a58a496ffa2944'
5
5
  SHA512:
6
- metadata.gz: 4ecebfdf31f9380e7739f80e43ac16ebf975f18a9e19fe17af922fb9652fe348e1cc858912404d2baf5c1ee108073e11e3037d1fbc75078c1779ba99f27a44f7
7
- data.tar.gz: e0b73c21bc741741f5e6808abd2f2fdbb97270f869f4ddd44bc5864d15f97be236514b12bf9d31aec25a8bc1c43a30b511c983f88caf4d91e6cffd957e1095b4
6
+ metadata.gz: 0c4bfbe6e6cbeaaf3440b71894f469e03b71eb272a570bd127923960eddec434750badd66d5258a79ee559b4c59f5be9141ab9595eb7f82b27108f5e26340751
7
+ data.tar.gz: 48fa29e4f97245598a2af38667e32b4bee11e87c65944c9570219fb764e0383a3d4bdaf5b71d403cde00f0e4dcff7bdb68f25566d2cb8f866b1f9c8ee1ae2913
data/lib/structure.rb CHANGED
@@ -1,20 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'structure/class_methods'
4
- require 'structure/utils'
5
4
 
6
5
  module Structure
6
+ def self.inspect(value)
7
+ if value.is_a?(::Array)
8
+ inspection = value.take(3)
9
+ .map { |subvalue| inspect(subvalue) }
10
+ .join(', ')
11
+ inspection += '...' if value.size > 3
12
+
13
+ "[#{inspection}]"
14
+ else
15
+ value.inspect
16
+ end
17
+ end
18
+
19
+ def self.serialize(value)
20
+ if value.respond_to?(:attributes)
21
+ value.attributes
22
+ elsif value.is_a?(::Array)
23
+ value.map { |subvalue| serialize(subvalue) }
24
+ else
25
+ value
26
+ end
27
+ end
28
+
7
29
  def self.included(base)
8
30
  base.extend ClassMethods
9
- base.__overwrite_initialize__
10
31
  end
11
32
 
33
+ # Returns a hash of all the attributes with their names as keys and the
34
+ # values of the attributes as values
12
35
  def attributes
13
36
  attribute_names.each_with_object({}) do |key, hash|
14
- hash[key] = Utils.serialize(send(key))
37
+ hash[key] = Structure.serialize(send(key))
15
38
  end
16
39
  end
17
40
 
41
+ # Returns an array of attribute names as strings
18
42
  def attribute_names
19
43
  self.class.attribute_names
20
44
  end
@@ -27,19 +51,9 @@ module Structure
27
51
 
28
52
  def inspect
29
53
  name = self.class.name || self.class.to_s.gsub(/[^\w:]/, '')
30
- values =
31
- attribute_names
32
- .map do |key|
33
- value = send(key)
34
- if value.is_a?(::Array)
35
- description = value.take(3).map(&:inspect).join(', ')
36
- description += '...' if value.size > 3
37
- "#{key}=[#{description}]"
38
- else
39
- "#{key}=#{value.inspect}"
40
- end
41
- end
42
- .join(', ')
54
+ values = attribute_names
55
+ .map { |key| "#{key}=#{Structure.inspect(send(key))}" }
56
+ .join(', ')
43
57
 
44
58
  "#<#{name} #{values}>"
45
59
  end
@@ -2,16 +2,19 @@
2
2
 
3
3
  module Structure
4
4
  module ClassMethods
5
+ # Returns an array of attribute names as strings
5
6
  attr_reader :attribute_names
6
7
 
7
8
  def self.extended(base)
8
9
  base.instance_variable_set :@attribute_names, []
10
+ base.send :__overwrite_initialize
9
11
  end
10
12
 
11
13
  def attribute(name, &block)
12
14
  name = name.to_s
13
15
 
14
- if name.chomp!('?')
16
+ if name.end_with?('?')
17
+ name = name.chop
15
18
  module_eval <<-CODE, __FILE__, __LINE__ + 1
16
19
  def #{name}?
17
20
  #{name}
@@ -21,48 +24,51 @@ module Structure
21
24
 
22
25
  module_eval <<-CODE, __FILE__, __LINE__ + 1
23
26
  def #{name}
24
- @__mutex__.synchronize {
25
- return @#{name} if defined?(@#{name})
27
+ @__mutex.synchronize {
28
+ break if @__table.key?("#{name}")
26
29
 
27
- @#{name} = __#{name}__
28
- @#{name}.freeze unless @#{name}.is_a?(Structure)
30
+ @__table["#{name}"] = __#{name}
31
+ @__table["#{name}"].freeze
29
32
 
30
- @#{name}
33
+ @__table["#{name}"]
31
34
  }
35
+
36
+ @__table["#{name}"]
32
37
  end
33
38
  CODE
34
39
 
35
- define_method "__#{name}__", block
36
- private "__#{name}__"
40
+ define_method "__#{name}", block
41
+ private "__#{name}"
37
42
 
38
43
  @attribute_names << name
39
44
 
40
45
  name.to_sym
41
46
  end
42
47
 
43
- def __overwrite_initialize__
48
+ private
49
+
50
+ def __overwrite_initialize
44
51
  class_eval do
45
- unless method_defined?(:__custom_initialize__)
46
- define_method :__custom_initialize__ do |*args|
47
- @__mutex__ = ::Thread::Mutex.new
48
- __original_initialize__(*args)
52
+ unless method_defined?(:__custom_initialize)
53
+ define_method :__custom_initialize do |*arguments, &block|
54
+ @__mutex = ::Thread::Mutex.new
55
+ @__table = {}
56
+ __original_initialize(*arguments, &block)
57
+ freeze
49
58
  end
50
59
  end
51
60
 
52
61
  return if instance_method(:initialize) ==
53
- instance_method(:__custom_initialize__)
62
+ instance_method(:__custom_initialize)
54
63
 
55
- alias_method :__original_initialize__, :initialize
56
- alias_method :initialize, :__custom_initialize__
64
+ alias_method :__original_initialize, :initialize
65
+ alias_method :initialize, :__custom_initialize
66
+ private :__custom_initialize, :__original_initialize
57
67
  end
58
68
  end
59
69
 
60
- private
61
-
62
70
  def method_added(name)
63
- return if name != :initialize
64
-
65
- __overwrite_initialize__
71
+ __overwrite_initialize if name == :initialize
66
72
  end
67
73
 
68
74
  def inherited(subclass)
@@ -2,31 +2,32 @@
2
2
 
3
3
  module Structure
4
4
  module ClassMethods
5
+ # Creates a double that mocks a value object built with Structure during a
6
+ # test
7
+ #
8
+ # The double has an alternative constructor that takes a hash to set values.
9
+ # Otherwise, it shares the public API of the mocked value object.
5
10
  def double
6
11
  klass = Class.new(self)
7
12
 
8
- (
9
- private_instance_methods(false) +
10
- protected_instance_methods(false) -
11
- [:initialize]
12
- ).each do |name|
13
+ (private_instance_methods(false) + protected_instance_methods(false) -
14
+ [:initialize]).each do |name|
13
15
  klass.send :undef_method, name
14
16
  end
15
17
 
16
18
  klass.module_eval do
17
- def initialize(data = {})
18
- data.each do |key, value|
19
+ def initialize(values = {})
20
+ values.each do |key, value|
19
21
  instance_variable_set :"@#{key}", value
20
22
  end
21
23
  end
22
24
 
23
25
  attribute_names.each do |name|
24
26
  module_eval <<-CODE, __FILE__, __LINE__ + 1
25
- def __#{name}__
27
+ private def __#{name}
26
28
  @#{name}
27
29
  end
28
30
  CODE
29
- private "__#{name}__"
30
31
  end
31
32
 
32
33
  module_eval(&Proc.new) if block_given?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Structure
4
- VERSION = '1.1.1'
4
+ VERSION = '1.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: structure
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hakan Ensari
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-24 00:00:00.000000000 Z
11
+ date: 2019-05-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -19,7 +19,6 @@ files:
19
19
  - lib/structure.rb
20
20
  - lib/structure/class_methods.rb
21
21
  - lib/structure/double.rb
22
- - lib/structure/utils.rb
23
22
  - lib/structure/version.rb
24
23
  homepage:
25
24
  licenses:
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Structure
4
- module Utils
5
- def self.serialize(value)
6
- if value.respond_to?(:attributes)
7
- value.attributes
8
- elsif value.is_a?(::Array)
9
- value.map { |subvalue| serialize(subvalue) }
10
- else
11
- value
12
- end
13
- end
14
- end
15
- end