smart_properties 1.15.0 → 1.16.3

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: 0466754454ac7feba9fa836c5b84ffaf04d2502084d6b385b6756f44cb119b34
4
- data.tar.gz: 47c46bfcce7352943062ac9be2f25a04ce1c3adbeb86d251a5b0aa20f012ddfa
3
+ metadata.gz: 4cab5fbc87f1af758c2b385feaed5c43cf2f7555f2f55322e1bbbfe47771a42d
4
+ data.tar.gz: a79f9fd570f548895fcd3cc4d65e7f6ba614692f0671e09ce70be6704b49428a
5
5
  SHA512:
6
- metadata.gz: 38f90027d577a4f7eca3e799980408aa6cb179af1d221f9b7c3212ba4385fa636057cfd620e4908c2f3c116c0475f04d9763a3fc00d2fd7a5349468b517f0095
7
- data.tar.gz: 3c4feb78a07b067ce593822861afa858ea29003354b8427c8bab12a2782de51f54a5027393b51c1817785a6b8ba57a2afa5dac54381dc58e7756d10e3bd7a3ad
6
+ metadata.gz: 42c3abfd70e12c52f185a49d6ccb2bfe4429a52eab2d18e8613058bc5687d6c525ac3ad3d5eaab75c1cbe092536673bb2c675d5adc2e26759a8a824e0ff4a096
7
+ data.tar.gz: 21eb0b7ab6ab434f512525f5a36fbf07c0a79ce53173c4c417ee379b52de737a4db1baf226019bc4d0eb813e2f7e6a502101f6674d6ba5703bc671bee1fd385c
@@ -0,0 +1,24 @@
1
+ name: Testing
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ test:
12
+
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: 2.6
21
+ - name: Install dependencies
22
+ run: bundle install
23
+ - name: Run tests
24
+ run: bundle exec rake
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.2
1
+ 2.6.6
data/README.md CHANGED
@@ -177,7 +177,7 @@ often. These validations can be found in the `SmartProperties::Validations` modu
177
177
 
178
178
  ```ruby
179
179
  class Article
180
- property :view_count, accepts: Ancestor.must_be(Number)
180
+ property :view_count, accepts: Ancestor.must_be(type: Number)
181
181
  end
182
182
  ```
183
183
 
@@ -1,7 +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
+ ALLOWED_DEFAULT_CLASSES = [Proc, Numeric, String, Range, TrueClass, FalseClass, NilClass, Symbol, Module].freeze
5
5
 
6
6
  attr_reader :name
7
7
  attr_reader :converter
@@ -157,12 +157,19 @@ module SmartProperties
157
157
  rescue NoMethodError => error
158
158
  # BasicObject does not respond to #nil? by default, so we need to double
159
159
  # check if somebody implemented it and it fails internally or if the
160
- # error occured because the method is actually not present. In the former
161
- # case, we want to raise the exception because there is something wrong
162
- # with the implementation of object#nil?. In the latter case we treat the
163
- # object as truthy because we don't know better.
164
- raise error if (class << object; self; end).public_instance_methods.include?(:nil?)
165
- false
160
+ # error occured because the method is actually not present.
161
+
162
+ # This is a workaround for the fact that #singleton_class is defined on Object, but not BasicObject.
163
+ the_singleton_class = (class << object; self; end)
164
+
165
+ if the_singleton_class.public_instance_methods.include?(:nil?)
166
+ # object defines #nil?, but it raised NoMethodError,
167
+ # something is wrong with the implementation, so raise the exception.
168
+ raise error
169
+ else
170
+ # treat the object as truthy because we don't know better.
171
+ false
172
+ end
166
173
  end
167
174
  end
168
175
  end
@@ -5,18 +5,19 @@ module SmartProperties
5
5
  attr_reader :parent
6
6
 
7
7
  def self.for(scope)
8
- parent = scope.ancestors[1..-1].find do |ancestor|
8
+ parents = scope.ancestors[1..-1].select do |ancestor|
9
9
  ancestor.ancestors.include?(SmartProperties) &&
10
10
  ancestor != scope &&
11
11
  ancestor != SmartProperties
12
12
  end
13
13
 
14
- if parent.nil?
15
- new
16
- else
17
- parent.properties.register(collection = new)
18
- collection
14
+ collection = new
15
+
16
+ parents.reverse.each do |parent|
17
+ parent.properties.register(collection)
19
18
  end
19
+
20
+ collection
20
21
  end
21
22
 
22
23
  def initialize
@@ -75,7 +76,7 @@ module SmartProperties
75
76
  end
76
77
 
77
78
  def refresh(parent_collection)
78
- @collection_with_parent_collection = parent_collection.merge(collection)
79
+ @collection_with_parent_collection.merge!(parent_collection)
79
80
  notify_children
80
81
  nil
81
82
  end
@@ -1,3 +1,3 @@
1
1
  module SmartProperties
2
- VERSION = "1.15.0"
2
+ VERSION = "1.16.3"
3
3
  end
@@ -91,6 +91,13 @@ module SmartProperties
91
91
  protected :property!
92
92
  end
93
93
 
94
+ module ModuleMethods
95
+ def included(target)
96
+ super
97
+ target.include(SmartProperties)
98
+ end
99
+ end
100
+
94
101
  class << self
95
102
  private
96
103
 
@@ -102,6 +109,7 @@ module SmartProperties
102
109
  #
103
110
  def included(base)
104
111
  base.extend(ClassMethods)
112
+ base.extend(ModuleMethods) unless base.is_a?(Class)
105
113
  end
106
114
  end
107
115
 
@@ -12,6 +12,10 @@ Gem::Specification.new do |gem|
12
12
  gem.summary = %q{SmartProperties – Ruby accessors on steroids}
13
13
  gem.homepage = ""
14
14
 
15
+ gem.metadata = {
16
+ "source_code_uri" => "https://github.com/t6d/smart_properties"
17
+ }
18
+
15
19
  gem.files = `git ls-files`.split($\)
16
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
@@ -20,6 +24,6 @@ Gem::Specification.new do |gem|
20
24
  gem.version = SmartProperties::VERSION
21
25
 
22
26
  gem.add_development_dependency "rspec", "~> 3.0"
23
- gem.add_development_dependency "rake", "~> 10.0"
27
+ gem.add_development_dependency "rake", "~> 13.0"
24
28
  gem.add_development_dependency "pry"
25
29
  end
@@ -14,6 +14,25 @@ RSpec.describe SmartProperties, 'configuration error' do
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
16
 
17
+ it "should accept default values that can't be mutated" do
18
+ valid_property_definition = lambda do
19
+ klass.class_eval do
20
+ property :proc, default: -> { }
21
+ property :numeric_float, default: 1.23
22
+ property :numeric_int, default: 456
23
+ property :string, default: "abc"
24
+ property :range, default: 123...456
25
+ property :bool_true, default: true
26
+ property :bool_false, default: false
27
+ property :nil, default: nil
28
+ property :symbol, default: :abc
29
+ property :module, default: Integer
30
+ end
31
+ end
32
+
33
+ expect(&valid_property_definition).not_to raise_error
34
+ end
35
+
17
36
  it "should not accept default values that may be mutated" do
18
37
  invalid_property_definition = lambda do
19
38
  klass.class_eval do
@@ -225,4 +225,86 @@ RSpec.describe SmartProperties, 'intheritance' do
225
225
  end
226
226
  end
227
227
  end
228
+
229
+ context "through modules" do
230
+ let(:m) do
231
+ m = Module.new do
232
+ include SmartProperties
233
+ property :m, default: 1
234
+ end
235
+ end
236
+
237
+ let(:n) do
238
+ n = Module.new do
239
+ include SmartProperties
240
+ property :n, default: 2
241
+ end
242
+ end
243
+
244
+ it "is supported" do
245
+ n = self.n
246
+ m = self.m
247
+ o = Module.new {}
248
+
249
+ klass = Class.new do
250
+ include m
251
+ include o
252
+ include n
253
+ end
254
+
255
+ n.module_eval do
256
+ property :p, default: 3
257
+ end
258
+
259
+ instance = klass.new
260
+
261
+ expect(instance.m).to eq(1)
262
+ expect(instance.n).to eq(2)
263
+ expect(instance.p).to eq(3)
264
+
265
+ expect { klass.new(m: 4, n: 5, p: 6) }.to_not raise_error
266
+ end
267
+
268
+ it "always extends module with ModuleMethods but never classes" do
269
+ n = self.n
270
+
271
+ klass = Class.new do
272
+ include n
273
+ end
274
+
275
+ module_singleton_class_ancestors = n.singleton_class.ancestors
276
+
277
+ expect(module_singleton_class_ancestors).to include(SmartProperties::ClassMethods)
278
+ expect(module_singleton_class_ancestors).to include(SmartProperties::ModuleMethods)
279
+
280
+ singleton_class_ancestors = klass.singleton_class.ancestors
281
+
282
+ expect(singleton_class_ancestors).to include(SmartProperties::ClassMethods)
283
+ expect(singleton_class_ancestors).not_to include(SmartProperties::ModuleMethods)
284
+ end
285
+
286
+ it "yields properly ordered properties – child properties have higher precedence than parent properties" do
287
+ n = self.n
288
+ m = self.m
289
+
290
+ parent = Class.new do
291
+ include m
292
+ include n
293
+ end
294
+ expect(parent.new.m).to eq(1)
295
+
296
+ child = Class.new(parent) do
297
+ property :m, default: 0
298
+ end
299
+ expect(child.new.m).to eq(0)
300
+
301
+ grandchild = Class.new(child)
302
+ expect(grandchild.new.m).to eq(0)
303
+
304
+ grandgrandchild = Class.new(grandchild) do
305
+ property :m, default: 1000
306
+ end
307
+ expect(grandgrandchild.new.m).to eq(1000)
308
+ end
309
+ end
228
310
  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.15.0
4
+ version: 1.16.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Tennhard
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-02 00:00:00.000000000 Z
11
+ date: 2021-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -62,6 +62,7 @@ executables: []
62
62
  extensions: []
63
63
  extra_rdoc_files: []
64
64
  files:
65
+ - ".github/workflows/testing.yml"
65
66
  - ".gitignore"
66
67
  - ".ruby-version"
67
68
  - ".yardopts"
@@ -95,8 +96,9 @@ files:
95
96
  - spec/writable_spec.rb
96
97
  homepage: ''
97
98
  licenses: []
98
- metadata: {}
99
- post_install_message:
99
+ metadata:
100
+ source_code_uri: https://github.com/t6d/smart_properties
101
+ post_install_message:
100
102
  rdoc_options: []
101
103
  require_paths:
102
104
  - lib
@@ -111,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
113
  - !ruby/object:Gem::Version
112
114
  version: '0'
113
115
  requirements: []
114
- rubygems_version: 3.0.3
115
- signing_key:
116
+ rubygems_version: 3.2.20
117
+ signing_key:
116
118
  specification_version: 4
117
119
  summary: SmartProperties – Ruby accessors on steroids
118
120
  test_files: