dockly-util 0.0.5 → 0.0.6

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.
@@ -22,29 +22,64 @@ module Dockly::Util::DSL
22
22
  end
23
23
  private :dsl_attribute
24
24
 
25
- def dsl_class_attribute(name, klass)
25
+ def dsl_class_attribute(name, klass, options={})
26
26
  unless klass.ancestors.include?(Dockly::Util::DSL)
27
- raise "#{self.class}.dsl_class_attribute requires a class that includes DSL"
28
- end
29
- define_method(name) do |sym = nil, &block|
30
- new_value = case
31
- when !block.nil? && !sym.nil? then klass.new!(:name => sym, &block)
32
- when block.nil? then klass.instances[sym]
33
- when sym.nil? then klass.new!(:name => :"#{self.name}_#{klass}", &block)
34
- end
35
- instance_variable_set(:"@#{name}", new_value) unless new_value.nil?
36
- instance_variable_get(:"@#{name}")
27
+ raise "#{self}.dsl_class_attribute requires a class that includes DSL"
37
28
  end
29
+ type = options.delete(:type) || Object
30
+ generated_related_name = :"#{self.underscore(self.demodulize(self.to_s))}"
31
+ related_name = options.delete(:related_name) || generated_related_name
32
+ define_forward_relation(name, related_name, self, klass, type)
33
+ define_reverse_relation(related_name, name, klass, self)
38
34
  end
39
35
  private :dsl_class_attribute
40
36
 
37
+ def define_forward_relation(name, related_name, current_class, klass, type)
38
+ current_class.instance_eval do
39
+ define_method(name) do |sym = nil, &block|
40
+ new_value = case
41
+ when !block.nil? && !sym.nil? then klass.new!(:name => sym, &block)
42
+ when block.nil? then klass.instances[sym]
43
+ when sym.nil? then klass.new!(:name => :"#{self.name}_#{klass}", &block)
44
+ end
45
+ unless new_value.nil?
46
+ if type.ancestors.include? Array
47
+ val = instance_variable_get(:"@#{name}") || []
48
+ instance_variable_set(:"@#{name}", val + [new_value])
49
+ else
50
+ instance_variable_set(:"@#{name}", new_value)
51
+ end
52
+ new_value.instance_variable_set(
53
+ :"@#{related_name}",
54
+ self
55
+ )
56
+ end
57
+ instance_variable_get(:"@#{name}")
58
+ end
59
+ end
60
+ end
61
+ private :define_forward_relation
62
+
63
+ def define_reverse_relation(name, related_name, current_class, klass)
64
+ current_class.instance_eval do
65
+ define_method(name) do
66
+ instance_variable_get(:"@#{name}")
67
+ end
68
+ end
69
+ end
70
+ private :define_reverse_relation
71
+
41
72
  def default_value(name, val = nil)
42
73
  default_values[name] = block_given? ? yield : val
43
74
  end
44
75
  private :default_value
45
76
 
46
77
  def default_values
47
- @default_values ||= {}
78
+ @default_values ||= if self.superclass.respond_to?(:default_values)
79
+ self.superclass.default_values
80
+ else
81
+ {}
82
+ end
48
83
  end
49
84
 
50
85
  def instances
@@ -59,6 +94,17 @@ module Dockly::Util::DSL
59
94
  end
60
95
  end
61
96
 
97
+ def underscore(camel_cased_word)
98
+ word = camel_cased_word.to_s.dup
99
+ word.gsub!('::', '/')
100
+ word.gsub!(/(?:([A-Za-z\d])|^)(#{/(?=a)b/})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
101
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
102
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
103
+ word.tr!("-", "_")
104
+ word.downcase!
105
+ word
106
+ end
107
+
62
108
  def generate_unique_name
63
109
  name = nil
64
110
  (0..(1.0 / 0.0)).each do |n|
@@ -1,5 +1,5 @@
1
1
  module Dockly
2
2
  module Util
3
- VERSION = '0.0.5'
3
+ VERSION = '0.0.6'
4
4
  end
5
5
  end
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ class IncludedClass
4
+ include Dockly::Util::DSL
5
+
6
+ dsl_attribute :ocean
7
+ end
8
+
9
+ class TestClass
10
+ include Dockly::Util::DSL
11
+
12
+ dsl_attribute :chips
13
+ dsl_class_attribute :meta, IncludedClass
14
+ end
15
+
16
+ class ArrayClass
17
+ include Dockly::Util::DSL
18
+
19
+ dsl_class_attribute :attr, IncludedClass, type: Array
20
+ end
21
+
22
+ describe Dockly::Util::DSL do
23
+ let(:included_class) { IncludedClass }
24
+ let(:test_class) { TestClass }
25
+ let(:array_class) { ArrayClass }
26
+
27
+ let(:test_instance) { test_class.new!(:name => 'Tony') }
28
+ let(:array_instance) { array_class.new! }
29
+
30
+ describe '.dsl_attribute' do
31
+ it 'defines a method for each name given' do
32
+ test_instance.should respond_to :chips
33
+ end
34
+
35
+ context 'the defined method(s)' do
36
+ context 'with 0 arguments' do
37
+ let(:test_val) { 'lays' }
38
+ before { test_instance.instance_variable_set(:@chips, test_val) }
39
+
40
+ it 'returns the value of the instance variable with a matching name' do
41
+ test_instance.chips.should == test_val
42
+ end
43
+ end
44
+
45
+ context 'with one argument' do
46
+ it 'sets the corresponding instance variable to the passed-in value' do
47
+ expect { test_instance.chips('bbq') }
48
+ .to change { test_instance.instance_variable_get(:@chips) }
49
+ .to 'bbq'
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '.dsl_class_attribute' do
56
+ context 'when the sceond argument is not a DSL' do
57
+ it 'raises an error' do
58
+ expect do
59
+ Class.new do
60
+ include Dockly::Util::DSL
61
+
62
+ dsl_class_attribute :test, Array
63
+ end
64
+ end.to raise_error
65
+ end
66
+ end
67
+
68
+ context 'when the second argument is a DSL' do
69
+ it 'defines a new method with the name of the first argument' do
70
+ test_instance.should respond_to :meta
71
+ array_instance.should respond_to :attr
72
+ end
73
+
74
+ it 'defines a new method on the DSL class with the name of the current class' do
75
+ included_class.new.should respond_to :test_class
76
+ included_class.new.should respond_to :array_class
77
+ end
78
+
79
+ context 'the method' do
80
+ context 'for a regular class attribute' do
81
+ let(:meta) { test_instance.instance_variable_get(:@meta) }
82
+
83
+ context 'when a symbol is given' do
84
+ context 'and a block is given' do
85
+ before { test_instance.meta(:yolo) { ocean 'Indian' } }
86
+
87
+ it 'creates a new instance of the specified Class with the name set' do
88
+ meta.name.should == :yolo
89
+ meta.ocean.should == 'Indian'
90
+ end
91
+ end
92
+
93
+ context 'and a block is not given' do
94
+ before { included_class.new!(:name => :test_name) { ocean 'Pacific' } }
95
+
96
+ it 'looks up the instance in its Class\'s .instances hash' do
97
+ test_instance.meta(:test_name).ocean.should == 'Pacific'
98
+ end
99
+ end
100
+ end
101
+
102
+ context 'when a symbol is not given' do
103
+ context 'and a block is given' do
104
+ before { test_instance.meta { ocean 'Atlantic' } }
105
+
106
+ it 'creates a new instance of the specified Class' do
107
+ meta.ocean.should == 'Atlantic'
108
+ end
109
+
110
+ it 'generates a name' do
111
+ meta.name.should == :"#{test_instance.name}_#{meta.class}"
112
+ end
113
+ end
114
+
115
+ context 'and a block is not given' do
116
+ before { test_instance.meta(:test) { ocean 'Artic' } }
117
+
118
+ it 'returns the corresponding instance variable' do
119
+ test_instance.meta.should == meta
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ context 'for an array class attribute' do
126
+ let(:attr) { array_instance.instance_variable_get(:@attr) }
127
+
128
+ context 'when a symbol is given' do
129
+ context 'and a block is given' do
130
+ before { array_instance.attr(:yolo) { ocean 'Indian' } }
131
+
132
+ it 'creates a new instance of the specified Class with the name set' do
133
+ expect(attr.length).to be == 1
134
+ expect(attr.first.ocean).to be == 'Indian'
135
+ end
136
+ end
137
+
138
+ context 'and a block is not given' do
139
+ before { included_class.new!(:name => :test_name) { ocean 'Pacific' } }
140
+
141
+ it 'looks up the instance in its Class\'s .instances hash' do
142
+ expect(array_instance.attr(:test_name).first.ocean).to be == 'Pacific'
143
+ end
144
+ end
145
+ end
146
+
147
+ context 'when a symbol is not given' do
148
+ context 'and a block is given' do
149
+ before { array_instance.attr { ocean 'Atlantic' } }
150
+
151
+ it 'creates a new instance of the specified Class' do
152
+ attr.first.ocean.should == 'Atlantic'
153
+ end
154
+
155
+ it 'generates a name' do
156
+ attr.first.name.should == :"#{array_instance.name}_#{IncludedClass.to_s}"
157
+ end
158
+ end
159
+
160
+ context 'and a block is not given' do
161
+ before { array_instance.attr(:test) { ocean 'Artic' } }
162
+
163
+ it 'returns the corresponding instance variable' do
164
+ array_instance.attr.should == attr
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ describe '#ensure_present!' do
174
+ context 'when at least one of the symbols is nil' do
175
+ it 'raises an error' do
176
+ expect { test_instance.send(:ensure_present!, :meta) }.to raise_error
177
+ end
178
+ end
179
+
180
+ context 'when each symbol is present' do
181
+ it 'does nothing' do
182
+ expect { test_instance.send(:ensure_present!, :name) }.to_not raise_error
183
+ end
184
+ end
185
+ end
186
+
187
+ describe '.default_value' do
188
+ context 'when a block is given' do
189
+ it 'calls the block and adds it to he default_values hash' do
190
+ test_class.send(:default_value, :meta) { included_class.new!(:name => :joey) }
191
+ test_class.default_values[:meta].name.should == :joey
192
+ end
193
+ end
194
+
195
+ context 'when a value is given' do
196
+ it 'adds the pair to the default_values hash' do
197
+ test_class.send(:default_value, :chips, 'Cool Ranch')
198
+ test_class.default_values[:chips].should == 'Cool Ranch'
199
+ end
200
+ end
201
+ end
202
+
203
+ describe '#initialize' do
204
+ context 'when a block is given' do
205
+ it 'is instance evaluated' do
206
+ test_class.new! { name :timmy }.name.should == :timmy
207
+ end
208
+ end
209
+
210
+ context 'when a hash is given' do
211
+ it 'sends each key value pair to the object as a message' do
212
+ test_class.new!(:name => :tommy).name.should == :tommy
213
+ end
214
+ end
215
+
216
+ context 'when there is a name' do
217
+ it 'adds the current instance to the class\'s instances hash' do
218
+ test_class.instances[:jillian].should be_nil
219
+ test_class.new! { name :jillian }
220
+ test_class.instances[:jillian].name.should == :jillian
221
+ end
222
+ end
223
+ end
224
+ end
File without changes
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
4
  require 'rspec'
5
+ require 'pry'
5
6
  require 'dockly/util'
6
7
 
7
8
  RSpec.configure do |config|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockly-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-07 00:00:00.000000000 Z
12
+ date: 2013-11-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -98,8 +98,8 @@ files:
98
98
  - lib/dockly/util/dsl.rb
99
99
  - lib/dockly/util/logger.rb
100
100
  - lib/dockly/util/version.rb
101
- - spec/dockl/util/dsl_spec.rb
102
- - spec/dockl/util/logger_spec.rb
101
+ - spec/dockly/util/dsl_spec.rb
102
+ - spec/dockly/util/logger_spec.rb
103
103
  - spec/spec_helper.rb
104
104
  homepage: https://github.com/swipely/dockly-util
105
105
  licenses:
@@ -127,7 +127,7 @@ signing_key:
127
127
  specification_version: 3
128
128
  summary: DSL made easy
129
129
  test_files:
130
- - spec/dockl/util/dsl_spec.rb
131
- - spec/dockl/util/logger_spec.rb
130
+ - spec/dockly/util/dsl_spec.rb
131
+ - spec/dockly/util/logger_spec.rb
132
132
  - spec/spec_helper.rb
133
133
  has_rdoc:
@@ -1,171 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Dockly::Util::DSL do
4
- let(:included_class) do
5
- Class.new do
6
- include Dockly::Util::DSL
7
-
8
- dsl_attribute :ocean
9
- end
10
- end
11
-
12
- let(:test_class) do
13
- klass = included_class
14
- Class.new do
15
- include Dockly::Util::DSL
16
-
17
- dsl_attribute :chips
18
- dsl_class_attribute :meta, klass
19
- end
20
- end
21
-
22
- subject { test_class.new!(:name => 'Tony') }
23
-
24
- describe '.dsl_attribute' do
25
- it 'defines a method for each name given' do
26
- subject.should respond_to :chips
27
- end
28
-
29
- context 'the defined method(s)' do
30
- context 'with 0 arguments' do
31
- let(:test_val) { 'lays' }
32
- before { subject.instance_variable_set(:@chips, test_val) }
33
-
34
- it 'returns the value of the instance variable with a matching name' do
35
- subject.chips.should == test_val
36
- end
37
- end
38
-
39
- context 'with one argument' do
40
- it 'sets the corresponding instance variable to the passed-in value' do
41
- expect { subject.chips('bbq') }
42
- .to change { subject.instance_variable_get(:@chips) }
43
- .to 'bbq'
44
- end
45
- end
46
- end
47
- end
48
-
49
- describe '.dsl_class_attribute' do
50
- context 'when the sceond argument is not a DSL' do
51
- it 'raises an error' do
52
- expect do
53
- Class.new do
54
- include Dockly::Util::DSL
55
-
56
- dsl_class_attribute :test, Array
57
- end
58
- end.to raise_error
59
- end
60
- end
61
-
62
- context 'when the second argument is a DSL' do
63
- it 'defines a new method with the name of the first argument' do
64
- subject.should respond_to :meta
65
- end
66
-
67
- context 'the method' do
68
- let(:meta) { subject.instance_variable_get(:@meta) }
69
-
70
- context 'when a symbol is given' do
71
- context 'and a block is given' do
72
- before { subject.meta(:yolo) { ocean 'Indian' } }
73
-
74
- it 'creates a new instance of the specified Class with the name set' do
75
- meta.name.should == :yolo
76
- meta.ocean.should == 'Indian'
77
- end
78
- end
79
-
80
- context 'and a block is not given' do
81
- before { included_class.new!(:name => :test_name) { ocean 'Pacific' } }
82
-
83
- it 'looks up the instance in its Class\'s .instances hash' do
84
- subject.meta(:test_name).ocean.should == 'Pacific'
85
- end
86
- end
87
- end
88
-
89
- context 'when a symbol is not given' do
90
- context 'and a block is given' do
91
- before { subject.meta { ocean 'Atlantic' } }
92
-
93
- it 'creates a new instance of the specified Class' do
94
- meta.ocean.should == 'Atlantic'
95
- end
96
-
97
- it 'generates a name' do
98
- meta.name.should == :"#{subject.name}_#{meta.class}"
99
- end
100
- end
101
-
102
- context 'and a block is not given' do
103
- before { subject.meta(:test) { ocean 'Artic' } }
104
-
105
- it 'returns the corresponding instance variable' do
106
- subject.meta.should == meta
107
- end
108
- end
109
- end
110
- end
111
- end
112
- end
113
-
114
- describe '#ensure_present!' do
115
- context 'when at least one of the symbols is nil' do
116
- it 'raises an error' do
117
- expect { subject.send(:ensure_present!, :meta) }.to raise_error
118
- end
119
- end
120
-
121
- context 'when each symbol is present' do
122
- it 'does nothing' do
123
- expect { subject.send(:ensure_present!, :name) }.to_not raise_error
124
- end
125
- end
126
- end
127
-
128
- describe '.default_value' do
129
- context 'when a block is given' do
130
- it 'calls the block and adds it to he default_values hash' do
131
- test_class.send(:default_value, :meta) { included_class.new!(:name => :joey) }
132
- test_class.default_values[:meta].name.should == :joey
133
- end
134
- end
135
-
136
- context 'when a value is given' do
137
- it 'adds the pair to the default_values hash' do
138
- test_class.send(:default_value, :chips, 'Cool Ranch')
139
- test_class.default_values[:chips].should == 'Cool Ranch'
140
- end
141
- end
142
- end
143
-
144
- describe '#initialize' do
145
- context 'when a block is given' do
146
- it 'is instance evaluated' do
147
- test_class.new! { name :timmy }.name.should == :timmy
148
- end
149
- end
150
-
151
- context 'when a hash is given' do
152
- it 'sends each key value pair to the object as a message' do
153
- test_class.new!(:name => :tommy).name.should == :tommy
154
- end
155
- end
156
-
157
- context 'when there is no name' do
158
- it 'raises an error' do
159
- expect { test_class.new! { chips 'Tortilla' } }.to raise_error
160
- end
161
- end
162
-
163
- context 'when there is a name' do
164
- it 'adds the current instance to the class\'s instances hash' do
165
- test_class.instances[:jillian].should be_nil
166
- test_class.new! { name :jillian }
167
- test_class.instances[:jillian].name.should == :jillian
168
- end
169
- end
170
- end
171
- end