structure 1.1.1 → 1.2.0

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: 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