cql 1.0.1 → 1.1.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.
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=