smart_properties 1.14.0 → 1.15.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: 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