cql 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cql.rb CHANGED
@@ -1,9 +1,5 @@
1
- if RUBY_VERSION < '1.9.2'
2
- require 'backports/1.9.2/array/rotate'
3
- end
4
-
5
1
  require 'cuke_modeler'
6
- require 'cql/dsl'
2
+ require 'cql/map_reduce'
7
3
 
8
4
  module CQL
9
5
 
@@ -12,6 +8,8 @@ module CQL
12
8
  attr_reader :data, :what
13
9
 
14
10
  def format_data data
11
+ space_data
12
+
15
13
  Array.new.tap do |result_array|
16
14
  data.each do |element|
17
15
  result_array << Hash.new.tap do |result|
@@ -34,11 +32,16 @@ module CQL
34
32
  # Populate configurables from DSL block
35
33
  self.instance_eval(&block)
36
34
 
35
+
36
+ raise(ArgumentError, "A query must specify a 'select' clause") unless @what
37
+ raise(ArgumentError, "A query must specify a 'from' clause") unless @from
38
+
39
+
37
40
  # Gather relevant objects from root object and filters
38
- @data= CQL::MapReduce.gather_objects(@data, @from, @filters)
41
+ @data = CQL::MapReduce.gather_objects(@data, @from, @filters)
39
42
 
40
43
  # Extract properties from gathered objects
41
- @data= format_output(@data)
44
+ @data = format_output(@data)
42
45
  end
43
46
 
44
47
 
@@ -50,7 +53,7 @@ module CQL
50
53
  end
51
54
 
52
55
  def determine_key(attribute, index)
53
- key = transform_stuff(@name_transforms, attribute, index) if @name_transforms
56
+ key = mapped_attribute(@name_transforms, attribute, index) if @name_transforms
54
57
 
55
58
  key || attribute
56
59
  end
@@ -59,7 +62,7 @@ module CQL
59
62
  original_value = attribute.is_a?(Symbol) ? special_value(element, attribute) : element.send(attribute)
60
63
 
61
64
  if @value_transforms
62
- value = transform_stuff(@value_transforms, attribute, index)
65
+ value = mapped_attribute(@value_transforms, attribute, index)
63
66
  value = value.call(original_value) if value.is_a?(Proc)
64
67
  end
65
68
 
@@ -72,20 +75,19 @@ module CQL
72
75
  when :self
73
76
  val = element
74
77
  else
75
- # todo - error message?
78
+ raise(ArgumentError, ":#{attribute} is not a valid attribute for selection.")
76
79
  end
77
80
 
78
81
  val
79
82
  end
80
83
 
81
- def transform_stuff(transforms, attribute, location)
84
+ def mapped_attribute(mappings, attribute, location)
82
85
  case
83
- when transforms.is_a?(Array)
84
- value = transforms[location]
85
- when transforms.is_a?(Hash)
86
- if transforms[attribute]
87
- value = transforms[attribute].first
88
- transforms[attribute].rotate!
86
+ when mappings.is_a?(Array)
87
+ value = mappings[location]
88
+ when mappings.is_a?(Hash)
89
+ if mappings[attribute]
90
+ value = mappings[attribute][location]
89
91
  end
90
92
  else
91
93
  # todo - add error message
@@ -94,6 +96,51 @@ module CQL
94
96
  value
95
97
  end
96
98
 
99
+ def space_data
100
+ space_renamings
101
+ space_transforms
102
+ end
103
+
104
+ def space_renamings
105
+ if @name_transforms.is_a?(Hash)
106
+ new_names = {}
107
+
108
+ @name_transforms.each_pair do |key, value|
109
+ new_names[key] = []
110
+
111
+ @what.each do |attribute|
112
+ if attribute == key
113
+ new_names[key] << value.shift
114
+ else
115
+ new_names[key] << nil
116
+ end
117
+ end
118
+ end
119
+
120
+ @name_transforms = new_names
121
+ end
122
+ end
123
+
124
+ def space_transforms
125
+ if @value_transforms.is_a?(Hash)
126
+ new_values = {}
127
+
128
+ @value_transforms.each_pair do |key, value|
129
+ new_values[key] = []
130
+
131
+ @what.each do |attribute|
132
+ if attribute == key
133
+ new_values[key] << value.shift
134
+ else
135
+ new_values[key] << nil
136
+ end
137
+ end
138
+ end
139
+
140
+ @value_transforms = new_values
141
+ end
142
+ end
143
+
97
144
  end
98
145
 
99
146
 
data/lib/cql/dsl.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'cql/map_reduce'
2
-
3
1
  module CQL
4
2
  module Dsl
5
3
 
@@ -26,6 +24,8 @@ module CQL
26
24
 
27
25
  #Select clause
28
26
  def select *what
27
+ what = [:self] if what.empty?
28
+
29
29
  @what ||= []
30
30
  @what.concat(what)
31
31
  end
@@ -44,7 +44,6 @@ module CQL
44
44
  def from(*targets)
45
45
  @from ||= []
46
46
 
47
- # todo - todo test the intermixing of shorthand and full classes as arguments
48
47
  targets.map! { |target| target.is_a?(String) ? determine_class(target) : target }
49
48
 
50
49
  @from.concat(targets)
@@ -1,21 +1,42 @@
1
1
  require 'cql/dsl'
2
2
  require 'cql/feature_filters'
3
3
  require 'cql/sso_filters'
4
+ require 'cql/dsl'
4
5
 
5
6
 
6
7
  module CQL
7
8
 
8
9
  class MapReduce
9
10
 
11
+ extend Dsl
12
+
10
13
  def self.gather_objects(current_object, target_classes, filters)
11
14
  gathered_objects = Array.new.tap { |gathered_objects| collect_all_in(target_classes, current_object, gathered_objects) }
12
15
 
13
16
  if filters
14
17
  filters.each do |filter|
15
18
  if filter.is_a?(Proc)
16
- gathered_objects.select!(&filter)
19
+ gathered_objects = filter_with_proc(gathered_objects, filter)
20
+ elsif filter.is_a?(Hash)
21
+ filter.keys.each do |filtered_class|
22
+ clazz = determine_class(filtered_class)
23
+
24
+ gathered_objects = gathered_objects.select do |object|
25
+ if object.is_a?(clazz)
26
+ if filter[filtered_class].is_a?(Proc)
27
+ filter[filtered_class].call(object)
28
+ else
29
+ # Must be a predefined filter otherwise
30
+ !filter_with_predefined([object], filter[filtered_class]).empty?
31
+ end
32
+ else
33
+ true
34
+ end
35
+ end
36
+ end
17
37
  else
18
- gathered_objects = filter.execute(gathered_objects)
38
+ # Must be a predefined filter otherwise
39
+ gathered_objects = filter_with_predefined(gathered_objects, filter)
19
40
  end
20
41
  end
21
42
  end
@@ -30,6 +51,14 @@ module CQL
30
51
  private
31
52
 
32
53
 
54
+ def filter_with_proc(objects, filter)
55
+ objects.select(&filter)
56
+ end
57
+
58
+ def filter_with_predefined(objects, filter)
59
+ filter.execute(objects)
60
+ end
61
+
33
62
  # Recursively gathers all objects of the given class(es) found in the passed object (including itself).
34
63
  def collect_all_in(targeted_classes, current_object, accumulated_objects)
35
64
  accumulated_objects << current_object if targeted_classes.any? { |targeted_class| current_object.is_a?(targeted_class) }
data/lib/cql/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CQL
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
data/spec/dsl_spec.rb CHANGED
@@ -1,21 +1,96 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'dsl' do
4
+
5
+
6
+ describe 'invalid query structure' do
7
+
8
+ it "will complain if no 'from' clause is specified" do
9
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
10
+
11
+ expect {
12
+ gs.query do
13
+ select
14
+ features
15
+ end
16
+ }.to raise_error(ArgumentError, "A query must specify a 'from' clause")
17
+ end
18
+
19
+ it "will complain if no 'select' clause is specified" do
20
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
21
+
22
+ expect {
23
+ gs.query do
24
+ from features
25
+ end
26
+ }.to raise_error(ArgumentError, "A query must specify a 'select' clause")
27
+ end
28
+
29
+ end
30
+
31
+
32
+ describe 'clause ordering' do
33
+
34
+ it 'handles intermixed clauses' do
35
+ # Clause ordering doesn't matter as long as any given type of clause is ordered correctly with respect to its multiple uses
36
+
37
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
38
+
39
+ results = gs.query do
40
+ with { |thing| thing.tags.include?('@one') }
41
+ as thing1
42
+ transform :self => lambda { |thing1| 1 }
43
+ select :self
44
+ as thing2
45
+ with scenarios => lambda { |scenario| scenario.name =~ /3/ }
46
+ from scenarios
47
+ select :self
48
+ transform :self => lambda { |thing2| 2 }
49
+ select name
50
+ end
51
+
52
+ expect(results.first).to eq('thing1' => 1, 'thing2' => 2, 'name' => 'Testing the slurping 3')
53
+ end
54
+
55
+ end
56
+
57
+
4
58
  describe "select" do
5
59
 
6
- describe "multiple selections" do
7
60
 
8
- it 'should handle an empty selection' do
9
- skip("It may be useful to be able to return both the underlying object and various attributes on it (which is the probably the intent of this query [assuming that it's not just a typo]) but I can't think of a clean way to do it. Behavior undefined for now.")
61
+ it 'complains if an unknown special attribute is queried' do
62
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
63
+
64
+ expect {
65
+ gs.query do
66
+ select :foo
67
+ from scenarios
68
+ end
69
+ }.to raise_error(ArgumentError, ":foo is not a valid attribute for selection.")
70
+ end
71
+
72
+
73
+ describe "multiple selections" do
10
74
 
75
+ it 'can freely mix empty selections and attribute selections' do
11
76
  gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
12
77
 
13
- result = gs.query do
14
- select
78
+ base_result = gs.query do
79
+ select :self
15
80
  select name
16
- from features
81
+ select :self
82
+ from scenarios
17
83
  end
18
84
 
85
+
86
+ expect(
87
+ gs.query do
88
+ select
89
+ select name
90
+ select
91
+ from scenarios
92
+ end
93
+ ).to eq(base_result)
19
94
  end
20
95
 
21
96
  end
@@ -57,7 +132,117 @@ describe 'dsl' do
57
132
  }.to raise_error(ArgumentError, "Class 'CukeModeler::NotARealClass' does not exist")
58
133
 
59
134
  end
135
+
136
+ it 'can freely mix shorthand and long-form names' do
137
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
138
+
139
+ # All long-form
140
+ base_result = gs.query do
141
+ select name
142
+ from CukeModeler::Scenario, CukeModeler::Feature
143
+ end
144
+
145
+ # All shorthand
146
+ expect(
147
+ gs.query do
148
+ select name
149
+ from scenarios, features
150
+ end
151
+ ).to eq(base_result)
152
+
153
+ # A mix of both
154
+ expect(
155
+ gs.query do
156
+ select name
157
+ from CukeModeler::Scenario, features
158
+ end
159
+ ).to eq(base_result)
160
+ end
161
+
60
162
  end
61
163
 
62
164
  end
165
+
166
+ describe "transform" do
167
+
168
+ describe "multiple targets" do
169
+
170
+ it 'does not apply more transforms than have been declared' do
171
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
172
+
173
+ results = gs.query do
174
+ select :self, :self, :self
175
+ as thing1, thing2, thing3
176
+ from scenarios
177
+ transform :self => lambda { |thing1| 1 }
178
+ transform :self => lambda { |thing2| 2 }
179
+ end
180
+
181
+ expect(results.first).to include('thing1' => 1, 'thing2' => 2)
182
+ expect(results.first).to_not include('thing3' => 1)
183
+ expect(results.first).to_not include('thing3' => 2)
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+
191
+ describe 'with' do
192
+
193
+ describe 'targeted' do
194
+
195
+ it 'can handle predefined filters' do
196
+ gs = CQL::Repository.new(@feature_fixtures_directory)
197
+
198
+ expect {
199
+ gs.query do
200
+ select name
201
+ from features, scenarios, outlines
202
+ with scenarios => name(/test/)
203
+ end
204
+ }.to_not raise_error
205
+ end
206
+
207
+ it 'can handle a block filter' do
208
+ gs = CQL::Repository.new(@feature_fixtures_directory)
209
+
210
+ expect {
211
+ gs.query do
212
+ select name
213
+ from features, scenarios, outlines
214
+ with scenarios => lambda { |scenario| true }
215
+ end
216
+ }.to_not raise_error
217
+ end
218
+
219
+ it 'can handle shorthand targets' do
220
+ gs = CQL::Repository.new(@feature_fixtures_directory)
221
+
222
+ expect {
223
+ gs.query do
224
+ select name
225
+ from features, scenarios, outlines
226
+ with scenarios => name(/test/)
227
+ end
228
+ }.to_not raise_error
229
+ end
230
+
231
+ it 'can handle multiple targets' do
232
+ gs = CQL::Repository.new(@feature_fixtures_directory)
233
+
234
+ expect {
235
+ gs.query do
236
+ select name
237
+ from features, scenarios, outlines
238
+ with scenarios => lambda { |scenario| true },
239
+ outlines => lambda { |outline| true }
240
+ end
241
+ }.to_not raise_error
242
+ end
243
+
244
+ end
245
+
246
+ end
247
+
63
248
  end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Eric Kessler
@@ -9,11 +10,12 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2015-09-20 00:00:00.000000000 Z
13
+ date: 2015-11-28 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: cuke_modeler
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
20
  - - ! '>='
19
21
  - !ruby/object:Gem::Version
@@ -21,20 +23,7 @@ dependencies:
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ! '>='
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: backports
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ! '>='
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :runtime
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
38
27
  requirements:
39
28
  - - ! '>='
40
29
  - !ruby/object:Gem::Version
@@ -42,6 +31,7 @@ dependencies:
42
31
  - !ruby/object:Gem::Dependency
43
32
  name: rake
44
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
45
35
  requirements:
46
36
  - - ! '>='
47
37
  - !ruby/object:Gem::Version
@@ -49,6 +39,7 @@ dependencies:
49
39
  type: :development
50
40
  prerelease: false
51
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
52
43
  requirements:
53
44
  - - ! '>='
54
45
  - !ruby/object:Gem::Version
@@ -56,6 +47,7 @@ dependencies:
56
47
  - !ruby/object:Gem::Dependency
57
48
  name: rspec
58
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
59
51
  requirements:
60
52
  - - ~>
61
53
  - !ruby/object:Gem::Version
@@ -63,6 +55,7 @@ dependencies:
63
55
  type: :development
64
56
  prerelease: false
65
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
66
59
  requirements:
67
60
  - - ~>
68
61
  - !ruby/object:Gem::Version
@@ -70,6 +63,7 @@ dependencies:
70
63
  - !ruby/object:Gem::Dependency
71
64
  name: cucumber
72
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
73
67
  requirements:
74
68
  - - ! '>='
75
69
  - !ruby/object:Gem::Version
@@ -77,6 +71,7 @@ dependencies:
77
71
  type: :development
78
72
  prerelease: false
79
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
80
75
  requirements:
81
76
  - - ! '>='
82
77
  - !ruby/object:Gem::Version
@@ -84,6 +79,7 @@ dependencies:
84
79
  - !ruby/object:Gem::Dependency
85
80
  name: simplecov
86
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
87
83
  requirements:
88
84
  - - ! '>='
89
85
  - !ruby/object:Gem::Version
@@ -91,6 +87,7 @@ dependencies:
91
87
  type: :development
92
88
  prerelease: false
93
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
94
91
  requirements:
95
92
  - - ! '>='
96
93
  - !ruby/object:Gem::Version
@@ -98,6 +95,7 @@ dependencies:
98
95
  - !ruby/object:Gem::Dependency
99
96
  name: racatt
100
97
  requirement: !ruby/object:Gem::Requirement
98
+ none: false
101
99
  requirements:
102
100
  - - ! '>='
103
101
  - !ruby/object:Gem::Version
@@ -105,6 +103,7 @@ dependencies:
105
103
  type: :development
106
104
  prerelease: false
107
105
  version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
108
107
  requirements:
109
108
  - - ! '>='
110
109
  - !ruby/object:Gem::Version
@@ -112,6 +111,7 @@ dependencies:
112
111
  - !ruby/object:Gem::Dependency
113
112
  name: coveralls
114
113
  requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
115
  requirements:
116
116
  - - ! '>='
117
117
  - !ruby/object:Gem::Version
@@ -119,6 +119,7 @@ dependencies:
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
122
123
  requirements:
123
124
  - - ! '>='
124
125
  - !ruby/object:Gem::Version
@@ -129,13 +130,13 @@ executables: []
129
130
  extensions: []
130
131
  extra_rdoc_files: []
131
132
  files:
132
- - lib/cql.rb
133
133
  - lib/cql/dsl.rb
134
134
  - lib/cql/feature_filters.rb
135
135
  - lib/cql/filters.rb
136
136
  - lib/cql/map_reduce.rb
137
137
  - lib/cql/sso_filters.rb
138
138
  - lib/cql/version.rb
139
+ - lib/cql.rb
139
140
  - spec/dsl_spec.rb
140
141
  - spec/filter_example_spec.rb
141
142
  - spec/filter_feature_dsl_spec.rb
@@ -147,14 +148,13 @@ files:
147
148
  - spec/name_filterable_specs.rb
148
149
  - spec/repository_spec.rb
149
150
  - spec/select_feature_dsl_spec.rb
150
- - spec/select_scen_outline_dsl_spec.rb
151
151
  - spec/select_scenario_dsl_spec.rb
152
+ - spec/select_scen_outline_dsl_spec.rb
152
153
  - spec/spec_helper.rb
153
154
  - spec/tag_filterable_specs.rb
154
155
  homepage: https://github.com/enkessler/cql
155
156
  licenses:
156
157
  - MIT
157
- metadata: {}
158
158
  post_install_message: ! '
159
159
 
160
160
  (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)
@@ -172,20 +172,22 @@ rdoc_options:
172
172
  require_paths:
173
173
  - lib
174
174
  required_ruby_version: !ruby/object:Gem::Requirement
175
+ none: false
175
176
  requirements:
176
177
  - - ! '>='
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
+ none: false
180
182
  requirements:
181
183
  - - ! '>='
182
184
  - !ruby/object:Gem::Version
183
185
  version: '0'
184
186
  requirements: []
185
187
  rubyforge_project:
186
- rubygems_version: 2.4.8
188
+ rubygems_version: 1.8.29
187
189
  signing_key:
188
- specification_version: 4
190
+ specification_version: 3
189
191
  summary: A gem providing functionality to query a Cucumber test suite.
190
192
  test_files:
191
193
  - spec/dsl_spec.rb
@@ -203,3 +205,4 @@ test_files:
203
205
  - spec/select_scen_outline_dsl_spec.rb
204
206
  - spec/spec_helper.rb
205
207
  - spec/tag_filterable_specs.rb
208
+ has_rdoc:
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YmJjZmVjY2MzZGQwMWIyNzIyNjA3ZjMxZDVlNGVhMGYwYWNhMjlmMQ==
5
- data.tar.gz: !binary |-
6
- ZTEwODIxZmEwZWFiYTM0MTI0YzI4MjZjMDZhYjk1OGRmOTkyYWE5Zg==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- ZjgxZDk5NjY1ZjA0YTNkYjJkNDIwZGVhYzVlMmEzODRjMmI1MDRkODk2Njc1
10
- YmUzM2ExYjYzYjY4M2I3YjExMjAwNTFjODhjZGRlY2ZhYjZkNTI0NzgwOGY2
11
- YTA5ZGE4MDIxOWFjMGU2ZjY1NmY3NzgyYTIxZjNlN2QzMGFhYjc=
12
- data.tar.gz: !binary |-
13
- M2NjN2RmZGZhNmUzYTE4NzY2OGE5ODM2ZTcwNDkyYjg5OWVmNDMyNTcxZWIy
14
- NDkyZTViZTljMGI0ZjRkMzBlMDM1ZDQwZGIzNDRmZTg0OTVmZTNlNmY1NmZh
15
- MTdjODU5OWIzYTU2YzJkYjIyYmQ5ODI1M2MyMDAyZjliYTZiNzM=