collection_of 1.0.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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NWNjZGU2ZGE3YzAxYWI5MWMwZmFhYmJjMGU4ZTY3NjY2ZDFjNmQzMA==
5
+ data.tar.gz: !binary |-
6
+ MDg1NWUzMTljNDFmN2Y4Mjg0M2JhZGNkOWM3ZTdiZGQxZDUwNWE5Mg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDkzYmFlODg2NjQ3Y2VhNGY1MmMxNmE3MDEyYjRiNTlhOWU2MzE2NmM4YzJh
10
+ OTNjYzU0MTk0ZTc2NmY5ZjM2NjdjM2UyNzRhMzhhZWI2MjY0ZjFkNjIyOTFk
11
+ YTA5OGMwZjQxMTY4YjUzZjU1NGRlYWY0NDE3ZjA1OTYxMmE1MjM=
12
+ data.tar.gz: !binary |-
13
+ ZmQ0NjNhNzBiZThjNjI0NjRlMGI0MGY5NDQzZWJhM2IyNDRmYThiOGE3N2Mx
14
+ YTRhZTlkODBmMTc2MDczOTFiZTNkNmM2MjJkZmY4NjI2ODYzMzIyNDQ0ZThi
15
+ ZjY0ZGQ5ODBlNmMyNTRjODZhNGI2YTI0OWUzMzg1Y2UxMmU4N2M=
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .idea
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in collection_of.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Daniel Vandersluis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # CollectionOf
2
+
3
+ Provides an Enumerable which acts as a collection of a certain type of object (and its subclasses,
4
+ unless `allow_subclasses` is set to `false` on initialization).
5
+
6
+ ## Usage
7
+
8
+ WidgetCollection = Collection[Widget]
9
+ # OR WidgetCollection = Collection.of(Widget)
10
+ # OR WidgetCollection = Collection.new(Widget)
11
+
12
+ wc = WidgetCollection.new
13
+ wc << Widget.new # all good!
14
+ wc << Wadget.new # => ArgumentError, "can only add Widget objects"
15
+
16
+ When a `Collection` is cloned, any items contained within the collection are cloned as well.
17
+
18
+ wc << Widget.new(:one)
19
+ wc << Widget.new(:two)
20
+ wc[:one] == wc.clone[:one] # => false
21
+
22
+ ## Installation
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ gem 'collection_of'
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ Or install it yourself as:
33
+
34
+ $ gem install collection_of
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'collection_of/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'collection_of'
8
+ spec.version = CollectionOf::VERSION
9
+ spec.authors = ['Daniel Vandersluis']
10
+ spec.email = ['dvandersluis@selfmgmt.com']
11
+ spec.description = %q{Ruby object for ease of collecting a certain type}
12
+ spec.summary = %q{Allows a collection of a given type of object to be worked with easily}
13
+ spec.homepage = 'https://github.com/dvandersluis/collection_of'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = %w(lib)
20
+
21
+ spec.add_dependency 'active_support', '>= 3.0.0'
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec'
25
+ end
@@ -0,0 +1,8 @@
1
+ require 'collection_of/collection'
2
+ require 'collection_of/version'
3
+
4
+ module CollectionOf
5
+ def self.[](klass, *args)
6
+ Collection.of(klass, *args)
7
+ end
8
+ end
@@ -0,0 +1,64 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+ require 'active_support/core_ext/array/extract_options'
3
+ require 'active_support/core_ext/object/duplicable'
4
+
5
+ class Collection
6
+ include Enumerable
7
+
8
+ attr_reader :klass, :options
9
+
10
+ delegate :empty?, :size, :each, :last, to: :@collection, allow_nil: true
11
+
12
+ class << self
13
+ alias_method :of, :new
14
+ alias_method :[], :new
15
+ end
16
+
17
+ def initialize(klass, *args)
18
+ @options = args.extract_options!
19
+ @klass = klass.is_a?(Class) ? klass : klass.class
20
+ @collection = [args.first].compact.flatten
21
+ end
22
+
23
+ def initialize_clone(*)
24
+ super
25
+
26
+ # Clone each item in the collection
27
+ @collection = @collection.inject([]) do |ary, item|
28
+ ary << (item.duplicable? ? item.clone : item)
29
+ ary
30
+ end
31
+ end
32
+
33
+ def [](item)
34
+ return nil if empty?
35
+
36
+ if item.is_a?(Fixnum)
37
+ @collection[item]
38
+ else
39
+ item = item.to_sym
40
+ detect{ |i| i.name.to_sym == item }
41
+ end
42
+ end
43
+
44
+ def new(*args, &block)
45
+ @klass.new(*args, &block).tap{ |obj| @collection << obj }
46
+ end
47
+
48
+ def <<(obj)
49
+ checker = @options.fetch(:allow_subclasses, true) ? :is_a? : :instance_of?
50
+ raise ArgumentError, "can only add #{@klass.name} objects" unless obj.send(checker, @klass)
51
+ @collection << obj
52
+ end
53
+
54
+ def except(*items)
55
+ items.map!(&:to_sym)
56
+ self.class.new(klass, reject{ |i| items.include?(i.name.to_sym) })
57
+ end
58
+
59
+ def ==(other)
60
+ return other == @collection if other.is_a?(self.class)
61
+ return @collection == other if other.is_a?(Array)
62
+ super
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module CollectionOf
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,189 @@
1
+ require 'collection_of'
2
+
3
+ class Widget
4
+ attr_accessor :name
5
+
6
+ def initialize(name = nil)
7
+ @name = name
8
+ end
9
+ end
10
+
11
+ class Wadget
12
+ attr_accessor :name
13
+
14
+ def initialize
15
+ @name = yield if block_given?
16
+ end
17
+ end
18
+
19
+ class SubWidget < Widget; end
20
+
21
+ describe Collection do
22
+ let(:w) { Widget.new }
23
+
24
+ describe "#initialize" do
25
+ context "when using #new" do
26
+ subject { Collection.new(Widget, [w], allow_subclasses: true) }
27
+ it { should be_a Collection }
28
+ it { should == [w] }
29
+ its(:klass) { should == Widget }
30
+ its(:options) { should == { allow_subclasses: true } }
31
+ end
32
+
33
+ context "when using the CollectionOf[] shorthand" do
34
+ subject { CollectionOf[Widget, [w], allow_subclasses: true] }
35
+ it { should be_a Collection }
36
+ it { should == [w] }
37
+ its(:klass) { should == Widget }
38
+ its(:options) { should == { allow_subclasses: true } }
39
+ end
40
+
41
+ context "when using the Collection[] shorthand" do
42
+ subject { Collection[Widget, [w], allow_subclasses: true] }
43
+ it { should be_a Collection }
44
+ it { should == [w] }
45
+ its(:klass) { should == Widget }
46
+ its(:options) { should == { allow_subclasses: true } }
47
+ end
48
+
49
+ context "when using Collection.of" do
50
+ subject { Collection.of(Widget, [w], allow_subclasses: true) }
51
+ it { should be_a Collection }
52
+ it { should == [w] }
53
+ its(:klass) { should == Widget }
54
+ its(:options) { should == { allow_subclasses: true } }
55
+ end
56
+ end
57
+
58
+ describe "#clone" do
59
+ let(:c) { described_class[Widget] }
60
+ let(:w1) { Widget.new(:one) }
61
+ let(:w2) { Widget.new(:two) }
62
+
63
+ before { c << w1 << w2 }
64
+
65
+ subject { c.clone }
66
+
67
+ it { should_not == c }
68
+ its(:first) { should_not == c.first }
69
+ its([1]) { should_not == c.first }
70
+
71
+ its('first.name') { should == :one }
72
+ end
73
+
74
+ describe "#[]" do
75
+ let(:w) { Widget.new("widgey") }
76
+ subject{ described_class.new(Widget) }
77
+
78
+ context "when the collection is empty" do
79
+ its([:foo]) { should be_nil }
80
+ end
81
+
82
+ context "when the collection is not empty" do
83
+ before { subject << w }
84
+
85
+ its([0]) { should == w }
86
+ its(['widgey']) { should == w }
87
+ its([:widgey]) { should == w }
88
+ its([1]) { should be_nil }
89
+ its([:fake]) { should be_nil }
90
+ end
91
+ end
92
+
93
+ describe "#new" do
94
+ subject { described_class[Widget] }
95
+
96
+ it "should create a new Widget" do
97
+ subject.new.should be_a Widget
98
+ end
99
+
100
+ it "should add it to the collection" do
101
+ subject.new
102
+ subject.count.should == 1
103
+ end
104
+
105
+ it "should add the new item to the end of the collection" do
106
+ 3.times { subject.new }
107
+ w = subject.new
108
+ subject[3].should == w
109
+ end
110
+
111
+ it "should pass on any arguments" do
112
+ w = subject.new('Smith')
113
+ w.name.should == 'Smith'
114
+ end
115
+
116
+ it "should pass on a given block" do
117
+ c = described_class[Wadget]
118
+ w = c.new { :test }
119
+ w.name.should == :test
120
+ end
121
+ end
122
+
123
+ describe "#<<" do
124
+ subject { described_class[Widget] }
125
+
126
+ it "should add like types to the collection" do
127
+ expect { subject << w }.to_not raise_error
128
+ subject.first.should == w
129
+ end
130
+
131
+ it "should not add unlike types to the collection" do
132
+ w = Wadget.new
133
+ expect { subject << w }.to raise_error(ArgumentError, "can only add Widget objects")
134
+ end
135
+
136
+ it "should add subclasses" do
137
+ expect { subject << SubWidget.new }.to_not raise_error
138
+ end
139
+
140
+ it "should not allow subclasses if allow_subclasses is false" do
141
+ c = described_class[Widget, allow_subclasses: false]
142
+ expect { c << SubWidget.new }.to raise_error(ArgumentError, "can only add Widget objects")
143
+ end
144
+ end
145
+
146
+ describe "#except" do
147
+ let(:c) { described_class[Widget] }
148
+ let(:w1) { Widget.new(:one) }
149
+ let(:w2) { Widget.new(:two) }
150
+
151
+ before { c << w1 << w2 }
152
+
153
+ context "when an include item is specified" do
154
+ subject { c.except(:one) }
155
+ it { should be_a described_class }
156
+ it { should == [w2] }
157
+ end
158
+
159
+ context "when all included items are specified" do
160
+ subject { c.except(:one, :two) }
161
+ it { should be_a described_class }
162
+ it { should be_empty }
163
+ end
164
+
165
+ context "when no included items are specified" do
166
+ subject { c.except(:three) }
167
+ it { should be_a described_class }
168
+ it { should == [w1, w2] }
169
+ end
170
+ end
171
+
172
+ describe "#==" do
173
+ let(:w1) { Widget.new(:one) }
174
+ let(:w2) { Widget.new(:two) }
175
+
176
+ subject { described_class[Widget] }
177
+ before { subject << w1 << w2 }
178
+
179
+ it { should == [w1, w2] }
180
+ it { should_not == [w1] }
181
+ it { should_not == [w2] }
182
+ it { should_not == [] }
183
+
184
+ it { should == described_class[Widget, [w1, w2]] }
185
+ it { should_not == described_class[Widget, [w1]] }
186
+ it { should_not == described_class[Widget, [w2]] }
187
+ it { should_not == described_class[Widget] }
188
+ end
189
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: collection_of
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Vandersluis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ type: :runtime
15
+ prerelease: false
16
+ name: active_support
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ type: :development
29
+ prerelease: false
30
+ name: bundler
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '1.3'
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ type: :development
43
+ prerelease: false
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ type: :development
57
+ prerelease: false
58
+ name: rspec
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Ruby object for ease of collecting a certain type
70
+ email:
71
+ - dvandersluis@selfmgmt.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - collection_of.gemspec
82
+ - lib/collection_of.rb
83
+ - lib/collection_of/collection.rb
84
+ - lib/collection_of/version.rb
85
+ - spec/collection_spec.rb
86
+ homepage: https://github.com/dvandersluis/collection_of
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.1.5
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Allows a collection of a given type of object to be worked with easily
110
+ test_files:
111
+ - spec/collection_spec.rb
112
+ has_rdoc: