restricted_struct 0.1.0 → 0.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
  SHA1:
3
- metadata.gz: 701f39867ce9703612900fe3fc7a02a5546860cd
4
- data.tar.gz: ec33a9f1adf85537047831ad5f52c7d02be8bc1f
3
+ metadata.gz: 4990efc33886647ac9d035269794891b1f4a5e7b
4
+ data.tar.gz: b11ebf6330ea5d3fced870c3c577cd01d61d650b
5
5
  SHA512:
6
- metadata.gz: 97fc5cf511d82388464d41532d3f41a063de18b89891c1c9ac5cbd728e2337e2dc6ce2825dbe156350a65c59ba66eee5dffdb1a2d627d13d195c9ba75e5a4b9c
7
- data.tar.gz: 96fa0f60b0005d2ff5da42137de9bcb8973bafe88e117854209fc532c2db24adb29f89970101f3128bce0a1058062bc0094f8f2dc9b965f95cae0e4bf3d2205b
6
+ metadata.gz: f2e2200102af51fcd8947504095a5c6b596d23f9b30e66913e2c751f15757d84f7858b53693bb55c29ce044193b42cf2d80174674b3c731acc5e2237bb906c79
7
+ data.tar.gz: e9a3d4fa4b02bd90a25170ad38c646c1b47d4838bdcb60644dbfebaa528cb73c0143332ae26128743ac6e664f4c6eeba129cf05c96c01164e6615316a4b7e6c7
data/README.md CHANGED
@@ -42,6 +42,41 @@ end
42
42
 
43
43
  Available access levels: `:private` and `:protected`.
44
44
 
45
+ ### Keyword arguments
46
+
47
+ ```ruby
48
+ class Rectangle < RestrictedStruct.new(:protected, :x1, :y1, :x2, :y2, :color => :white)
49
+ # ...
50
+ end
51
+ ```
52
+
53
+ This will create a struct with 5 fields: x1, y1, x2, y2 and color. But color will default to `:white` if not provided.
54
+ And color can be assigned while instantiating a value of this class either as 5th parameter or as keyword argument, i.e.:
55
+
56
+ ```ruby
57
+ rect = Rectangle[20, 30, 60, 50, :red]
58
+ # is the same as:
59
+ rect = Rectangle[20, 30, 60, 50, :color => :red]
60
+ ```
61
+
62
+ By the way, nothing forbids you from specifying any fields as keyword arguments:
63
+
64
+ ```ruby
65
+ rect = Rectangle[20, 30, :x2 => 60, :y2 => 50]
66
+ # or even all of them:
67
+ rect = Rectangle[:x1 => 20, :y1 => 30, :x2 => 60, :y2 => 50, :color => :black]
68
+ ```
69
+
70
+ Just be careful when specifying the same fields simultaneously as normal params and as part of keyword arguments hash, for example:
71
+
72
+ ```ruby
73
+ rect = Rectangle[20, 30, 60, 50, :x2 => 55]
74
+ # is essentially the same as
75
+ rect = Rectangle[20, 30, 55, 50]
76
+ ```
77
+
78
+ Which means 3rd argument was overwritten by corresponding keyword argument.
79
+
45
80
  ## Contributing
46
81
 
47
82
  1. Fork it ( https://github.com/waterlink/restricted_struct/fork )
@@ -1,2 +1,3 @@
1
1
  require "restricted_struct/definition"
2
+ require "restricted_struct/support"
2
3
  require "restricted_struct/version"
@@ -7,7 +7,20 @@ class RestrictedStruct < Struct
7
7
 
8
8
  class << self
9
9
  def new(access_level, *properties)
10
- super(*properties, &access_restriction(access_level, properties))
10
+ properties, defaults = Support.extract_keyword_args(properties)
11
+ properties.concat(defaults.keys)
12
+ super(*properties, &access_restriction(access_level, properties)).with_defaults(defaults)
13
+ end
14
+
15
+ def defaults
16
+ @defaults ||= {}
17
+ end
18
+
19
+ protected
20
+
21
+ def with_defaults(defaults)
22
+ @defaults = defaults
23
+ self
11
24
  end
12
25
 
13
26
  private
@@ -26,4 +39,15 @@ class RestrictedStruct < Struct
26
39
  properties + properties.map { |name| :"#{name}=" }
27
40
  end
28
41
  end
42
+
43
+ def initialize(*values)
44
+ values, keyword_args = Support.extract_keyword_args(values)
45
+ members.each_with_index do |name, index|
46
+ # 1.8 compatibility
47
+ key = name.to_sym
48
+ values[index] ||= self.class.defaults[key]
49
+ values[index] = keyword_args[key] if keyword_args.has_key?(key)
50
+ end
51
+ super(*values)
52
+ end
29
53
  end
@@ -0,0 +1,9 @@
1
+ module RestrictedStruct::Support
2
+ class << self
3
+ def extract_keyword_args(array)
4
+ array = array.dup
5
+ keyword_args = Hash === array[-1] ? array.pop : {}
6
+ [array, keyword_args]
7
+ end
8
+ end
9
+ end
@@ -1 +1 @@
1
- RestrictedStruct::VERSION = "0.1.0"
1
+ RestrictedStruct::VERSION = "0.2.0"
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = RestrictedStruct::VERSION
9
9
  spec.authors = ["Alexey Fedorov", "Anselm Helbig"]
10
10
  spec.email = ["alexey.fedorov@wimdu.com", "anselm.helbig@wimdu.com"]
11
- spec.summary = %q{Create Struct-s with private or protected attributes}
11
+ spec.summary = %q{Create Struct-s with private or protected attributes. Reduce your boilerplate code to nothing}
12
12
  spec.description = %q{This gem allows to use ruby's Struct, but automatically hides all the attributes as private or protected, which provides higher level of encapsulation.}
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
@@ -0,0 +1,25 @@
1
+ RSpec.describe RestrictedStruct::Support do
2
+ describe ".extract_keyword_args" do
3
+ it "splits into list and last parameter if it is a hash" do
4
+ expect(described_class.extract_keyword_args(
5
+ [1, 2, 3, { :color => :red }]
6
+ )).to eq([[1, 2, 3], { :color => :red }])
7
+ end
8
+
9
+ it "last parameter defaults to an empty hash" do
10
+ expect(described_class.extract_keyword_args(
11
+ [1, 2, 3, 4]
12
+ )).to eq([[1, 2, 3, 4], {}])
13
+ end
14
+
15
+ it "list defaults to an empty list if only hash provided" do
16
+ expect(described_class.extract_keyword_args(
17
+ [{ :color => :red }]
18
+ )).to eq([[], { :color => :red }])
19
+ end
20
+
21
+ it "returns empty list and hash if provided array is empty" do
22
+ expect(described_class.extract_keyword_args([])).to eq([[], {}])
23
+ end
24
+ end
25
+ end
@@ -21,6 +21,33 @@ RSpec.describe RestrictedStruct do
21
21
  }.to raise_error(NoMethodError, /#{access_level} method `properties='/)
22
22
  end
23
23
  end
24
+ end
25
+
26
+ describe "keyword arguments" do
27
+ let(:rectangle) { RestrictedStruct.new(:protected, :x1, :y1, :x2, :y2, :color => :white) }
28
+
29
+ it "equals to specified default if omitted" do
30
+ expect(rectangle.new(1, 2, 3, 4)).to eq(rectangle.new(1, 2, 3, 4, :white))
31
+ end
24
32
 
33
+ it "can be overriden by specifying as normal argument" do
34
+ expect(rectangle.new(1, 2, 3, 4, :red)).not_to eq(rectangle.new(1, 2, 3, 4))
35
+ end
36
+
37
+ it "can be overriden by specifying as keyword argument" do
38
+ expect(rectangle.new(1, 2, 3, 4, :color => :red)).not_to eq(rectangle.new(1, 2, 3, 4))
39
+ end
40
+
41
+ it "being specified as keyword argument is equivalent to specifying as normal argument" do
42
+ expect(rectangle.new(1, 2, 3, 4, :red)).to eq(rectangle.new(1, 2, 3, 4, :color => :red))
43
+ end
44
+
45
+ it "can be used instead of normal arguments" do
46
+ expect(rectangle.new(1, 2, :x2 => 3, :y2 => 4)).to eq(rectangle.new(1, 2, 3, 4))
47
+ end
48
+
49
+ it "overrides value of normal argument" do
50
+ expect(rectangle.new(1, 2, 3, 4, :x2 => 5)).to eq(rectangle.new(1, 2, 5, 4))
51
+ end
25
52
  end
26
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restricted_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Fedorov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-21 00:00:00.000000000 Z
12
+ date: 2015-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -57,8 +57,10 @@ files:
57
57
  - Rakefile
58
58
  - lib/restricted_struct.rb
59
59
  - lib/restricted_struct/definition.rb
60
+ - lib/restricted_struct/support.rb
60
61
  - lib/restricted_struct/version.rb
61
62
  - restricted_struct.gemspec
63
+ - spec/restricted_struct/support_spec.rb
62
64
  - spec/restricted_struct_spec.rb
63
65
  - spec/spec_helper.rb
64
66
  homepage: ''
@@ -84,7 +86,9 @@ rubyforge_project:
84
86
  rubygems_version: 2.2.2
85
87
  signing_key:
86
88
  specification_version: 4
87
- summary: Create Struct-s with private or protected attributes
89
+ summary: Create Struct-s with private or protected attributes. Reduce your boilerplate
90
+ code to nothing
88
91
  test_files:
92
+ - spec/restricted_struct/support_spec.rb
89
93
  - spec/restricted_struct_spec.rb
90
94
  - spec/spec_helper.rb