smart_properties 1.14.0 → 1.15.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: 845948d63c5a647048b44f96e405808bdf3697430323a9ebf29b57c13ed157c9
4
- data.tar.gz: be7cc4c03ab7bcba3dbdaea8a04676ada44f50f07d3f5a323926098af6560c97
3
+ metadata.gz: 0466754454ac7feba9fa836c5b84ffaf04d2502084d6b385b6756f44cb119b34
4
+ data.tar.gz: 47c46bfcce7352943062ac9be2f25a04ce1c3adbeb86d251a5b0aa20f012ddfa
5
5
  SHA512:
6
- metadata.gz: fc5370fce67258915440c7e6fe3b02b1207d04ab1716be3f22b478f7ebf1d22807115b2f7aa7639b82030ad4309a69941606b20d6a64815e9afacd4fb48cdafb
7
- data.tar.gz: 003da1d3daab182873e5ccd4ba6359707309fc06161f095c52803cfd6e1d3cb055c0baa59886aaed8b51f3eb5d05d4c6efdfc6188445a6e6de8d4c48a607b8ec
6
+ metadata.gz: 38f90027d577a4f7eca3e799980408aa6cb179af1d221f9b7c3212ba4385fa636057cfd620e4908c2f3c116c0475f04d9763a3fc00d2fd7a5349468b517f0095
7
+ data.tar.gz: 3c4feb78a07b067ce593822861afa858ea29003354b8427c8bab12a2782de51f54a5027393b51c1817785a6b8ba57a2afa5dac54381dc58e7756d10e3bd7a3ad
@@ -1,6 +1,7 @@
1
1
  module SmartProperties
2
2
  class Property
3
3
  MODULE_REFERENCE = :"@_smart_properties_method_scope"
4
+ ALLOWED_DEFAULT_CLASSES = [Proc, Numeric, String, Range, TrueClass, FalseClass, NilClass, Symbol].freeze
4
5
 
5
6
  attr_reader :name
6
7
  attr_reader :converter
@@ -27,6 +28,11 @@ module SmartProperties
27
28
 
28
29
  @instance_variable_name = :"@#{name}"
29
30
 
31
+ unless ALLOWED_DEFAULT_CLASSES.any? { |cls| @default.is_a?(cls) }
32
+ raise ConfigurationError, "Default attribute value #{@default.inspect} cannot be specified as literal, "\
33
+ "use the syntax `default: -> { ... }` instead."
34
+ end
35
+
30
36
  unless attrs.empty?
31
37
  raise ConfigurationError, "SmartProperties do not support the following configuration options: #{attrs.keys.map { |m| m.to_s }.sort.join(', ')}."
32
38
  end
@@ -66,7 +72,7 @@ module SmartProperties
66
72
  end
67
73
 
68
74
  def default(scope)
69
- @default.kind_of?(Proc) ? scope.instance_exec(&@default) : @default
75
+ @default.kind_of?(Proc) ? scope.instance_exec(&@default) : @default.dup
70
76
  end
71
77
 
72
78
  def accepts?(value, scope)
@@ -1,3 +1,3 @@
1
1
  module SmartProperties
2
- VERSION = "1.14.0"
2
+ VERSION = "1.15.0"
3
3
  end
@@ -41,7 +41,7 @@ RSpec.describe SmartProperties do
41
41
  default_title = double(to_title: 'chunky')
42
42
 
43
43
  DummyClass.new do
44
- property :title, converts: :to_title, accepts: String, required: true, default: default_title
44
+ property :title, converts: :to_title, accepts: String, required: true, default: -> { default_title }
45
45
  end
46
46
  end
47
47
 
@@ -49,7 +49,7 @@ RSpec.describe SmartProperties do
49
49
 
50
50
  it "should return a property's configuration with #to_h" do
51
51
  expect(klass.properties.values.first.to_h).to match(
52
- accepter: String, converter: :to_title, default: an_instance_of(RSpec::Mocks::Double),
52
+ accepter: String, converter: :to_title, default: an_instance_of(Proc),
53
53
  instance_variable_name: :@title, name: :title, reader: :title, required: true
54
54
  )
55
55
  end
@@ -13,5 +13,19 @@ RSpec.describe SmartProperties, 'configuration error' do
13
13
 
14
14
  expect(&invalid_property_definition).to raise_error(SmartProperties::ConfigurationError, "SmartProperties do not support the following configuration options: invalid_option_1, invalid_option_2, invalid_option_3.")
15
15
  end
16
+
17
+ it "should not accept default values that may be mutated" do
18
+ invalid_property_definition = lambda do
19
+ klass.class_eval do
20
+ property :title, default: []
21
+ end
22
+ end
23
+
24
+ expect(&invalid_property_definition).to(
25
+ raise_error(SmartProperties::ConfigurationError,
26
+ "Default attribute value [] cannot be specified as literal, "\
27
+ "use the syntax `default: -> { ... }` instead.")
28
+ )
29
+ end
16
30
  end
17
31
  end
@@ -48,4 +48,72 @@ RSpec.describe SmartProperties, 'default values' do
48
48
  end
49
49
  end
50
50
  end
51
+
52
+ context "when defining a new property with a literal default value" do
53
+ context 'with a numeric default' do
54
+ subject(:klass) { DummyClass.new { property :var, default: 123 } }
55
+
56
+ it 'accepts the default and returns it' do
57
+ instance = klass.new
58
+ expect(instance.var).to(be(123))
59
+ end
60
+ end
61
+
62
+ context 'with a string default' do
63
+ DEFAULT_VALUE = 'a string'
64
+ subject(:klass) { DummyClass.new { property :var, default: DEFAULT_VALUE } }
65
+
66
+ it 'accepts the default and returns it' do
67
+ instance = klass.new
68
+ expect(instance.var).to(eq(DEFAULT_VALUE))
69
+ end
70
+
71
+ it 'returns a copy of the string' do
72
+ instance = klass.new
73
+ expect(instance.var).to_not(be(DEFAULT_VALUE))
74
+ end
75
+
76
+ it 'mutating the instance variable does not mutate the original' do
77
+ instance = klass.new
78
+ instance.var[0] = 'o'
79
+ expect(DEFAULT_VALUE).to(eq('a string'))
80
+ end
81
+ end
82
+
83
+ context 'with a range default' do
84
+ subject(:klass) { DummyClass.new { property :var, default: 1..2 } }
85
+
86
+ it 'accepts the default and returns it' do
87
+ instance = klass.new
88
+ expect(instance.var).to(eq(1..2))
89
+ end
90
+ end
91
+
92
+ context 'with a true default' do
93
+ subject(:klass) { DummyClass.new { property :var, default: true } }
94
+
95
+ it 'accepts the default and returns it' do
96
+ instance = klass.new
97
+ expect(instance.var).to(be(true))
98
+ end
99
+ end
100
+
101
+ context 'with a false default' do
102
+ subject(:klass) { DummyClass.new { property :var, default: false } }
103
+
104
+ it 'accepts the default and returns it' do
105
+ instance = klass.new
106
+ expect(instance.var).to(be(false))
107
+ end
108
+ end
109
+
110
+ context 'with a symbol default' do
111
+ subject(:klass) { DummyClass.new { property :var, default: :foo } }
112
+
113
+ it 'accepts the default and returns it' do
114
+ instance = klass.new
115
+ expect(instance.var).to(be(:foo))
116
+ end
117
+ end
118
+ end
51
119
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_properties
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Tennhard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-13 00:00:00.000000000 Z
11
+ date: 2019-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec