set_builder 2.0.0.beta3 → 2.0.0.beta4
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/assets/javascripts/set_builder.js +19 -13
- data/lib/set_builder/constraint.rb +11 -8
- data/lib/set_builder/modifier/arguments.rb +50 -0
- data/lib/set_builder/modifier/base.rb +18 -16
- data/lib/set_builder/modifiers/date_preposition.rb +8 -8
- data/lib/set_builder/modifiers/number_preposition.rb +4 -4
- data/lib/set_builder/modifiers/string_preposition.rb +8 -8
- data/lib/set_builder/parser.rb +36 -0
- data/lib/set_builder/trait.rb +2 -33
- data/lib/set_builder/version.rb +1 -1
- data/spec/unit/set_builder.spec.js +31 -6
- data/test/constraint_test.rb +36 -12
- data/test/modifier_test.rb +28 -28
- metadata +52 -27
- checksums.yaml +0 -7
@@ -30,12 +30,14 @@ var SetBuilder = (function() {
|
|
30
30
|
return _modifiers;
|
31
31
|
},
|
32
32
|
getValueMap: function(key) {
|
33
|
-
|
33
|
+
var valueMap = _value_maps[key];
|
34
|
+
return typeof valueMap == 'function' ? valueMap() : valueMap;
|
34
35
|
},
|
35
|
-
getValue: function(key, value) {
|
36
|
+
getValue: function(key, value, valueMap) {
|
37
|
+
var map = valueMap || SetBuilder.getValueMap(key);
|
36
38
|
if(Object.prototype.toString.call(value) == '[object Array]') {
|
37
39
|
var getValue = arguments.callee;
|
38
|
-
var values = value.__collect(function(value) { return getValue(key, value) });
|
40
|
+
var values = value.__collect(function(value) { return getValue(key, value, map) });
|
39
41
|
switch(values.length) {
|
40
42
|
case 0: return '';
|
41
43
|
case 1: return values[0];
|
@@ -43,9 +45,7 @@ var SetBuilder = (function() {
|
|
43
45
|
default: return values.slice(0, -1).join(', ') + ', or ' + values[values.length - 1];
|
44
46
|
}
|
45
47
|
}
|
46
|
-
|
47
|
-
var match = value.toString(),
|
48
|
-
map = SetBuilder.getValueMap(key);
|
48
|
+
var match = value.toString();
|
49
49
|
if(map) {
|
50
50
|
var pair = map.__find(function(i) { return (i[0] == match) });
|
51
51
|
return pair ? pair[1] : '(unknown)';
|
@@ -174,11 +174,16 @@ SetBuilder.Modifier = function(_name, _operator, _values, _params) {
|
|
174
174
|
}
|
175
175
|
|
176
176
|
this.toString = function() {
|
177
|
-
var words = [_operator.replace(/_/, ' ')];
|
178
|
-
|
179
|
-
|
177
|
+
var words = [_operator.replace(/_/, ' '), ' '];
|
178
|
+
var __values = _values.dup();
|
179
|
+
for(var i=0; i<_params.length; i++) {
|
180
|
+
if(_params[i][0] == 'arg') {
|
181
|
+
words.push(SetBuilder.getValue(_params[i][1], __values.shift()));
|
182
|
+
} else {
|
183
|
+
words.push(_params[i][1])
|
184
|
+
}
|
180
185
|
}
|
181
|
-
return words.join('
|
186
|
+
return words.join('');
|
182
187
|
}
|
183
188
|
|
184
189
|
};
|
@@ -247,13 +252,14 @@ SetBuilder.Modifiers = function(_modifiers) {
|
|
247
252
|
var operator = args.operator;
|
248
253
|
if(!operator) throw 'An operator name was not supplied.'
|
249
254
|
|
250
|
-
var params = this.params_for_operator(modifier_type, operator)
|
255
|
+
var params = this.params_for_operator(modifier_type, operator)
|
256
|
+
var paramsLength = params.__select(function(token) { return token[0] == 'arg' }).length;
|
251
257
|
var values = args.values;
|
252
258
|
|
253
259
|
if(!values) values = [];
|
254
260
|
if(!(values instanceof Array)) values = [values];
|
255
|
-
if(values.length !=
|
256
|
-
throw ('The operator "' + operator.toString() + '" expects ' +
|
261
|
+
if(values.length != paramsLength) {
|
262
|
+
throw ('The operator "' + operator.toString() + '" expects ' + paramsLength + ' arguments but received ' + values.length + '.');
|
257
263
|
}
|
258
264
|
|
259
265
|
return new SetBuilder.Modifier(name, operator, values, params);
|
@@ -23,7 +23,17 @@ module SetBuilder
|
|
23
23
|
@params = params
|
24
24
|
|
25
25
|
@direct_object = params[direct_object_type] if trait.requires_direct_object?
|
26
|
-
|
26
|
+
|
27
|
+
# Map supplied enum values to what the Trait has defined.
|
28
|
+
# If there are any discrepancies or missing values, fill them
|
29
|
+
# in with values that will work.
|
30
|
+
enum_values = params[:enums] || []
|
31
|
+
@enums = trait.enums.each_with_index.map do |expected_values, i|
|
32
|
+
value = enum_values[i]
|
33
|
+
value = expected_values[0] unless expected_values.include?(value)
|
34
|
+
value
|
35
|
+
end
|
36
|
+
|
27
37
|
modifiers = params.fetch(:modifiers, [])
|
28
38
|
@modifiers = trait.modifiers.each_with_index.map { |modifier, i|
|
29
39
|
modifier.new(modifiers[i] || {}) }
|
@@ -38,13 +48,6 @@ module SetBuilder
|
|
38
48
|
def errors
|
39
49
|
[].tap do |errors|
|
40
50
|
errors.push "#{direct_object_type} is blank" if direct_object_required? && direct_object.nil?
|
41
|
-
if enums.length != trait.enums.length
|
42
|
-
errors.push "should have values for #{trait.enums.length} enums"
|
43
|
-
else
|
44
|
-
trait.enums.each_with_index do |expected_values, i|
|
45
|
-
errors.push "enum ##{i + 1} should be #{expected_values.map { |value| "'#{value}'" }.to_sentence(two_words_connector: " or ", last_word_connector: ", or ")}" unless expected_values.member?(enums[i])
|
46
|
-
end
|
47
|
-
end
|
48
51
|
errors.concat modifiers.flat_map(&:errors)
|
49
52
|
end
|
50
53
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "set_builder/parser"
|
2
|
+
|
3
|
+
module SetBuilder
|
4
|
+
module Modifier
|
5
|
+
class Arguments
|
6
|
+
attr_reader :arguments, :expression, :tokens
|
7
|
+
|
8
|
+
include Parser
|
9
|
+
|
10
|
+
def initialize(expression)
|
11
|
+
@expression = expression.respond_to?(:each) ? map_legacy_arguments(expression) : expression
|
12
|
+
@tokens = parse(@expression)
|
13
|
+
end
|
14
|
+
|
15
|
+
def arity
|
16
|
+
types.count
|
17
|
+
end
|
18
|
+
|
19
|
+
def types
|
20
|
+
@types ||= @tokens
|
21
|
+
.select { |token, _| token == :arg }
|
22
|
+
.map { |_, type| type }
|
23
|
+
end
|
24
|
+
|
25
|
+
def as_json(*)
|
26
|
+
tokens.map { |(token, value)| [token.to_s, value] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s(values)
|
30
|
+
_values = values.dup
|
31
|
+
tokens.map do |token, token_value|
|
32
|
+
if token == :arg
|
33
|
+
ValueMap.to_s(token_value, _values.shift)
|
34
|
+
else
|
35
|
+
token_value
|
36
|
+
end
|
37
|
+
end.join
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def map_legacy_arguments(arguments)
|
43
|
+
_expression = arguments.map { |arg| "{#{arg}}" }.join(" ")
|
44
|
+
puts "DEPRECATED: SetBuilder::Modifier should use expression style argumenents now e.g.-> \"#{_expression}\""
|
45
|
+
_expression
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "set_builder/modifier/arguments"
|
2
|
+
|
1
3
|
module SetBuilder
|
2
4
|
module Modifier
|
3
5
|
class Base
|
@@ -43,11 +45,11 @@ module SetBuilder
|
|
43
45
|
|
44
46
|
def errors_with_values
|
45
47
|
[].tap do |errors|
|
46
|
-
|
47
|
-
if values.length !=
|
48
|
-
errors.push "wrong number of arguments; expected #{
|
48
|
+
arguments = self.class.parsed_operators[operator] || Arguments.new("")
|
49
|
+
if values.length != arguments.arity
|
50
|
+
errors.push "wrong number of arguments; expected #{arguments.arity} (#{arguments.types.join(", ")})"
|
49
51
|
else
|
50
|
-
errors.concat values.each_with_index.flat_map { |value, i| errors_with_value_type(value, types[i]) }
|
52
|
+
errors.concat values.each_with_index.flat_map { |value, i| errors_with_value_type(value, arguments.types[i]) }
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -78,13 +80,16 @@ module SetBuilder
|
|
78
80
|
|
79
81
|
|
80
82
|
|
81
|
-
def to_s
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
def to_s
|
84
|
+
arguments = self.class.parsed_operators[operator] || Arguments.new("")
|
85
|
+
operator.to_s.gsub(/_/, " ") + " " + arguments.to_s(values)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
def self.parsed_operators
|
91
|
+
@parsed_operators ||= Hash[operators.map { |operator, arguments|
|
92
|
+
[operator, Arguments.new(arguments)] }]
|
88
93
|
end
|
89
94
|
|
90
95
|
|
@@ -96,11 +101,8 @@ module SetBuilder
|
|
96
101
|
|
97
102
|
|
98
103
|
def self.to_hash
|
99
|
-
|
100
|
-
|
101
|
-
hash[operator.to_s] = array.map {|type| type.to_s }
|
102
|
-
end
|
103
|
-
hash
|
104
|
+
Hash[parsed_operators.map { |operator, arguments|
|
105
|
+
[operator.to_s, arguments.as_json] }]
|
104
106
|
end
|
105
107
|
|
106
108
|
|
@@ -7,14 +7,14 @@ module SetBuilder
|
|
7
7
|
|
8
8
|
def self.operators
|
9
9
|
{
|
10
|
-
:ever =>
|
11
|
-
:before =>
|
12
|
-
:after =>
|
13
|
-
:on =>
|
14
|
-
:during_month =>
|
15
|
-
:during_year =>
|
16
|
-
:in_the_last =>
|
17
|
-
:between =>
|
10
|
+
:ever => "",
|
11
|
+
:before => "{date}",
|
12
|
+
:after => "{date}",
|
13
|
+
:on => "{date}",
|
14
|
+
:during_month => "{month}",
|
15
|
+
:during_year => "{year}",
|
16
|
+
:in_the_last => "{number} {period}",
|
17
|
+
:between => "{date} and {date}"
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
@@ -7,10 +7,10 @@ module SetBuilder
|
|
7
7
|
|
8
8
|
def self.operators
|
9
9
|
{
|
10
|
-
:is =>
|
11
|
-
:is_less_than =>
|
12
|
-
:is_greater_than =>
|
13
|
-
:is_between =>
|
10
|
+
:is => "{number}",
|
11
|
+
:is_less_than => "{number}",
|
12
|
+
:is_greater_than => "{number}",
|
13
|
+
:is_between => "{number} and {number}"
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
@@ -7,14 +7,14 @@ module SetBuilder
|
|
7
7
|
|
8
8
|
def self.operators
|
9
9
|
{
|
10
|
-
:contains =>
|
11
|
-
:does_not_contain =>
|
12
|
-
:begins_with =>
|
13
|
-
:does_not_begin_with =>
|
14
|
-
:ends_with =>
|
15
|
-
:does_not_end_with =>
|
16
|
-
:is =>
|
17
|
-
:is_not =>
|
10
|
+
:contains => "{string}",
|
11
|
+
:does_not_contain => "{string}",
|
12
|
+
:begins_with => "{string}",
|
13
|
+
:does_not_begin_with => "{string}",
|
14
|
+
:ends_with => "{string}",
|
15
|
+
:does_not_end_with => "{string}",
|
16
|
+
:is => "{string}",
|
17
|
+
:is_not => "{string}"
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module SetBuilder
|
2
|
+
module Parser
|
3
|
+
|
4
|
+
def parse(expression)
|
5
|
+
tokenizer = Regexp.union(LEXER.values)
|
6
|
+
expression.split(tokenizer).each_with_object([]) do |lexeme, output|
|
7
|
+
next if lexeme.empty?
|
8
|
+
token = token_for(lexeme)
|
9
|
+
output.push [token, value_for(token, lexeme)]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def token_for(lexeme)
|
14
|
+
LEXER.each { |token, pattern| return token if pattern.match(lexeme) }
|
15
|
+
:string
|
16
|
+
end
|
17
|
+
|
18
|
+
def value_for(token, lexeme)
|
19
|
+
case token
|
20
|
+
when :name, :modifier, :arg then lexeme[1...-1]
|
21
|
+
when :enum then lexeme[1...-1].split("|")
|
22
|
+
when :direct_object_type then lexeme[1..-1]
|
23
|
+
else lexeme
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
LEXER = {
|
28
|
+
name: /("[^"]+")/,
|
29
|
+
direct_object_type: /(:[\w\-\.]+)/,
|
30
|
+
enum: /(\[[^\]]+\])/,
|
31
|
+
modifier: /(<\w+>)/,
|
32
|
+
arg: /(\{[^\}]+\})/
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/set_builder/trait.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require "set_builder/constraint"
|
2
2
|
require "set_builder/modifier"
|
3
|
+
require "set_builder/parser"
|
3
4
|
|
4
5
|
|
5
6
|
module SetBuilder
|
6
7
|
class Trait
|
7
8
|
attr_reader :expression, :tokens, :name, :modifiers, :direct_object_type, :enums
|
8
9
|
|
10
|
+
include Parser
|
9
11
|
|
10
12
|
|
11
13
|
def initialize(expression, &block)
|
@@ -65,38 +67,5 @@ module SetBuilder
|
|
65
67
|
|
66
68
|
|
67
69
|
|
68
|
-
def parse(expression)
|
69
|
-
tokenizer = Regexp.union(LEXER.values)
|
70
|
-
expression.split(tokenizer).each_with_object([]) do |lexeme, output|
|
71
|
-
next if lexeme.empty?
|
72
|
-
token = token_for(lexeme)
|
73
|
-
output.push [token, value_for(token, lexeme)]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def token_for(lexeme)
|
78
|
-
LEXER.each { |token, pattern| return token if pattern.match(lexeme) }
|
79
|
-
:string
|
80
|
-
end
|
81
|
-
|
82
|
-
def value_for(token, lexeme)
|
83
|
-
case token
|
84
|
-
when :name then lexeme[1...-1]
|
85
|
-
when :enum then lexeme[1...-1].split("|")
|
86
|
-
when :modifier then lexeme[1...-1]
|
87
|
-
when :direct_object_type then lexeme[1..-1]
|
88
|
-
else lexeme
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
LEXER = {
|
93
|
-
name: /("[^"]+")/,
|
94
|
-
direct_object_type: /(:[\w\-\.]+)/,
|
95
|
-
enum: /(\[[^\]]+\])/,
|
96
|
-
modifier: /(<\w+>)/
|
97
|
-
}.freeze
|
98
|
-
|
99
|
-
|
100
|
-
|
101
70
|
end
|
102
71
|
end
|
data/lib/set_builder/version.rb
CHANGED
@@ -32,10 +32,13 @@ describe 'SetBuilder'
|
|
32
32
|
|
33
33
|
SetBuilder.registerModifiers({
|
34
34
|
string: {
|
35
|
-
contains: ['string'],
|
36
|
-
begins_with: ['string'],
|
37
|
-
ends_with: ['string'],
|
38
|
-
is: ['string']
|
35
|
+
contains: [['arg', 'string']],
|
36
|
+
begins_with: [['arg', 'string']],
|
37
|
+
ends_with: [['arg', 'string']],
|
38
|
+
is: [['arg', 'string']]
|
39
|
+
},
|
40
|
+
date: {
|
41
|
+
between: [['arg', 'date'], ['string', ' and '], ['arg', 'date']]
|
39
42
|
}
|
40
43
|
});
|
41
44
|
|
@@ -60,6 +63,20 @@ describe 'SetBuilder'
|
|
60
63
|
|
61
64
|
|
62
65
|
|
66
|
+
describe '.registerValueMap'
|
67
|
+
it 'should accept an array of arrays as a valueMap'
|
68
|
+
SetBuilder.registerValueMap('name', [['1', 'John'], ['2', 'Susan']]);
|
69
|
+
expect(SetBuilder.getValueMap('name')).to(eql, [['1', 'John'], ['2', 'Susan']]);
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should accept and call a function as a valueMap'
|
73
|
+
var events = [['1', 'Band Rehearsal']];
|
74
|
+
SetBuilder.registerValueMap('event', function () { return events });
|
75
|
+
expect(SetBuilder.getValueMap('event')).to(eql, events);
|
76
|
+
events.push(['2', 'Basketball Practice']);
|
77
|
+
expect(SetBuilder.getValueMap('event')).to(eql, events);
|
78
|
+
end
|
79
|
+
end
|
63
80
|
|
64
81
|
describe '.getValueMap'
|
65
82
|
it 'should return an array of arrays'
|
@@ -80,7 +97,7 @@ describe 'SetBuilder'
|
|
80
97
|
|
81
98
|
describe '.getValueMaps'
|
82
99
|
it 'should return the names of the value maps registered'
|
83
|
-
expect(SetBuilder.getValueMaps()).to(eql, ['school']);
|
100
|
+
expect(SetBuilder.getValueMaps()).to(eql, ['school', 'name', 'event']);
|
84
101
|
end
|
85
102
|
end
|
86
103
|
|
@@ -139,7 +156,7 @@ describe 'SetBuilder'
|
|
139
156
|
|
140
157
|
describe '.length'
|
141
158
|
it 'should have parsed the data structure correctly'
|
142
|
-
|
159
|
+
expect(modifiers.length()).to(be, 2);
|
143
160
|
end
|
144
161
|
end
|
145
162
|
|
@@ -195,6 +212,14 @@ describe 'SetBuilder'
|
|
195
212
|
var expected_string = 'who are not awesome, who have not attended Concordia, who have not died, and whose name is Jerome'
|
196
213
|
expect(set.toString()).to(eql, expected_string);
|
197
214
|
end
|
215
|
+
|
216
|
+
it 'should generate the natural language description of a set with extra text in modifier arguments'
|
217
|
+
var set = new SetBuilder.Set([
|
218
|
+
{ trait: 'born', modifiers: [{ operator: 'between', values: ['Jan 1, 2016', 'Jan 2, 2016'] }]}
|
219
|
+
])
|
220
|
+
var expected_string = 'who were born between Jan 1, 2016 and Jan 2, 2016';
|
221
|
+
expect(set.toString()).to(eql, expected_string);
|
222
|
+
end
|
198
223
|
end
|
199
224
|
|
200
225
|
end
|
data/test/constraint_test.rb
CHANGED
@@ -3,6 +3,8 @@ require "test_helper"
|
|
3
3
|
class ConstraintTest < ActiveSupport::TestCase
|
4
4
|
include SetBuilder
|
5
5
|
|
6
|
+
attr_reader :trait, :constraint
|
7
|
+
|
6
8
|
|
7
9
|
test "constraints find correct modifiers" do
|
8
10
|
trait = $friend_traits[:name]
|
@@ -29,6 +31,40 @@ class ConstraintTest < ActiveSupport::TestCase
|
|
29
31
|
|
30
32
|
|
31
33
|
|
34
|
+
context "When a Constraint has fewer enum values than the Trait expects, it" do
|
35
|
+
setup do
|
36
|
+
@trait = Trait.new('who [is|is not] "awesome" at [basketball|golf|hockey]')
|
37
|
+
@constraint = trait.apply({enums: ["is not"]})
|
38
|
+
end
|
39
|
+
|
40
|
+
should "be valid" do
|
41
|
+
assert constraint.valid?, "The constraint was not valid: #{constraint.errors.join(";")}"
|
42
|
+
end
|
43
|
+
|
44
|
+
should "fill in the missing values with the first option the Trait defines" do
|
45
|
+
assert_equal "who is not awesome at basketball", constraint.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
context "When a Constraint is given an enum value that the Trait doesn't expect, it" do
|
52
|
+
setup do
|
53
|
+
@trait = Trait.new('who [is|is not] "awesome" at [basketball|golf|hockey]')
|
54
|
+
@constraint = trait.apply({enums: ["are not", "soccer"]})
|
55
|
+
end
|
56
|
+
|
57
|
+
should "be valid" do
|
58
|
+
assert constraint.valid?, "The constraint was not valid: #{constraint.errors.join(";")}"
|
59
|
+
end
|
60
|
+
|
61
|
+
should "replace the value with the first option the Trait defines" do
|
62
|
+
assert_equal "who is awesome at basketball", constraint.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
32
68
|
context "A constraint" do
|
33
69
|
should "be invalid if it is missing a direct object" do
|
34
70
|
trait = Trait.new('who "attended" :school')
|
@@ -36,18 +72,6 @@ class ConstraintTest < ActiveSupport::TestCase
|
|
36
72
|
assert_match /school is blank/, constraint.errors.join
|
37
73
|
end
|
38
74
|
|
39
|
-
should "be invalid if it is missing an enumeration" do
|
40
|
-
trait = Trait.new('who [is|is not] "awesome"')
|
41
|
-
constraint = trait.apply({})
|
42
|
-
assert_match /should have values for 1 enums/, constraint.errors.join
|
43
|
-
end
|
44
|
-
|
45
|
-
should "be invalid if it supplies an unexpected value for an enumeration" do
|
46
|
-
trait = Trait.new('who [is|is not] "awesome"')
|
47
|
-
constraint = trait.apply(enums: ["is totally"])
|
48
|
-
assert_match /should be 'is' or 'is not'/, constraint.errors.join
|
49
|
-
end
|
50
|
-
|
51
75
|
should "be invalid if it supplies an unexpected value for a modifier's operator" do
|
52
76
|
trait = Trait.new('whose "name" <string>')
|
53
77
|
constraint = trait.apply(modifiers: [{ operator: "starts_with", values: ["Jer"] }])
|
data/test/modifier_test.rb
CHANGED
@@ -55,14 +55,14 @@ class ModifierTest < ActiveSupport::TestCase
|
|
55
55
|
|
56
56
|
test "converting modifier to json" do
|
57
57
|
expected_results = {
|
58
|
-
"contains" => ["string"],
|
59
|
-
"does_not_contain" => ["string"],
|
60
|
-
"begins_with" => ["string"],
|
61
|
-
"does_not_begin_with" => ["string"],
|
62
|
-
"ends_with" => ["string"],
|
63
|
-
"does_not_end_with" => ["string"],
|
64
|
-
"is" => ["string"],
|
65
|
-
"is_not" => ["string"]
|
58
|
+
"contains" => [["arg", "string"]],
|
59
|
+
"does_not_contain" => [["arg", "string"]],
|
60
|
+
"begins_with" => [["arg", "string"]],
|
61
|
+
"does_not_begin_with" => [["arg", "string"]],
|
62
|
+
"ends_with" => [["arg", "string"]],
|
63
|
+
"does_not_end_with" => [["arg", "string"]],
|
64
|
+
"is" => [["arg", "string"]],
|
65
|
+
"is_not" => [["arg", "string"]]
|
66
66
|
}.to_json
|
67
67
|
assert_equal expected_results, SetBuilder::Modifier.for(:string).to_json
|
68
68
|
end
|
@@ -71,29 +71,29 @@ class ModifierTest < ActiveSupport::TestCase
|
|
71
71
|
expected_results = {
|
72
72
|
"date" => {
|
73
73
|
"ever" => [],
|
74
|
-
"
|
75
|
-
"
|
76
|
-
"on" => ["date"],
|
77
|
-
"
|
78
|
-
"
|
79
|
-
"
|
80
|
-
"between" => ["date", "date"]
|
74
|
+
"before" => [["arg", "date"]],
|
75
|
+
"after" => [["arg", "date"]],
|
76
|
+
"on" => [["arg", "date"]],
|
77
|
+
"during_month"=> [["arg", "month"]],
|
78
|
+
"during_year" => [["arg", "year"]],
|
79
|
+
"in_the_last" => [["arg", "number"], ["string", " "], ["arg", "period"]],
|
80
|
+
"between" => [["arg", "date"], ["string", " and "], ["arg", "date"]]
|
81
81
|
},
|
82
|
-
"number"=> {
|
83
|
-
"is"=>["number"],
|
84
|
-
"is_less_than"=>["number"],
|
85
|
-
"is_greater_than"=>["number"],
|
86
|
-
"is_between"=>["number", "number"]
|
82
|
+
"number" => {
|
83
|
+
"is"=>[["arg", "number"]],
|
84
|
+
"is_less_than"=>[["arg", "number"]],
|
85
|
+
"is_greater_than"=>[["arg", "number"]],
|
86
|
+
"is_between"=>[["arg", "number"], ["string", " and "], ["arg", "number"]]
|
87
87
|
},
|
88
88
|
"string" => {
|
89
|
-
"contains" => ["string"],
|
90
|
-
"does_not_contain" => ["string"],
|
91
|
-
"begins_with" => ["string"],
|
92
|
-
"does_not_begin_with" => ["string"],
|
93
|
-
"ends_with" => ["string"],
|
94
|
-
"does_not_end_with" => ["string"],
|
95
|
-
"is" => ["string"],
|
96
|
-
"is_not" => ["string"]
|
89
|
+
"contains" => [["arg", "string"]],
|
90
|
+
"does_not_contain" => [["arg", "string"]],
|
91
|
+
"begins_with" => [["arg", "string"]],
|
92
|
+
"does_not_begin_with" => [["arg", "string"]],
|
93
|
+
"ends_with" => [["arg", "string"]],
|
94
|
+
"does_not_end_with" => [["arg", "string"]],
|
95
|
+
"is" => [["arg", "string"]],
|
96
|
+
"is_not" => [["arg", "string"]]
|
97
97
|
}
|
98
98
|
}
|
99
99
|
assert_equal expected_results, $friend_traits.modifiers.to_hash
|
metadata
CHANGED
@@ -1,139 +1,158 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: set_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta4
|
5
|
+
prerelease: 6
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Bob Lail
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: rails
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- -
|
19
|
+
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: 4.2.0
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- -
|
27
|
+
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: 4.2.0
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: arel
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- -
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: '0'
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- -
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: '0'
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: bundler
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
|
-
- -
|
51
|
+
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
47
53
|
version: '1.3'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
|
-
- -
|
59
|
+
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '1.3'
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: rake
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
|
-
- -
|
67
|
+
- - ! '>='
|
60
68
|
- !ruby/object:Gem::Version
|
61
69
|
version: '0'
|
62
70
|
type: :development
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
|
-
- -
|
75
|
+
- - ! '>='
|
67
76
|
- !ruby/object:Gem::Version
|
68
77
|
version: '0'
|
69
78
|
- !ruby/object:Gem::Dependency
|
70
79
|
name: jspec
|
71
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
72
82
|
requirements:
|
73
|
-
- -
|
83
|
+
- - ! '>='
|
74
84
|
- !ruby/object:Gem::Version
|
75
85
|
version: '0'
|
76
86
|
type: :development
|
77
87
|
prerelease: false
|
78
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
79
90
|
requirements:
|
80
|
-
- -
|
91
|
+
- - ! '>='
|
81
92
|
- !ruby/object:Gem::Version
|
82
93
|
version: '0'
|
83
94
|
- !ruby/object:Gem::Dependency
|
84
95
|
name: pry
|
85
96
|
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
86
98
|
requirements:
|
87
|
-
- -
|
99
|
+
- - ! '>='
|
88
100
|
- !ruby/object:Gem::Version
|
89
101
|
version: '0'
|
90
102
|
type: :development
|
91
103
|
prerelease: false
|
92
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
93
106
|
requirements:
|
94
|
-
- -
|
107
|
+
- - ! '>='
|
95
108
|
- !ruby/object:Gem::Version
|
96
109
|
version: '0'
|
97
110
|
- !ruby/object:Gem::Dependency
|
98
111
|
name: shoulda-context
|
99
112
|
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - ! '>='
|
102
116
|
- !ruby/object:Gem::Version
|
103
117
|
version: '0'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
107
122
|
requirements:
|
108
|
-
- -
|
123
|
+
- - ! '>='
|
109
124
|
- !ruby/object:Gem::Version
|
110
125
|
version: '0'
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
127
|
name: minitest-reporters
|
113
128
|
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
114
130
|
requirements:
|
115
|
-
- -
|
131
|
+
- - ! '>='
|
116
132
|
- !ruby/object:Gem::Version
|
117
133
|
version: '0'
|
118
134
|
type: :development
|
119
135
|
prerelease: false
|
120
136
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
121
138
|
requirements:
|
122
|
-
- -
|
139
|
+
- - ! '>='
|
123
140
|
- !ruby/object:Gem::Version
|
124
141
|
version: '0'
|
125
142
|
- !ruby/object:Gem::Dependency
|
126
143
|
name: timecop
|
127
144
|
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
128
146
|
requirements:
|
129
|
-
- -
|
147
|
+
- - ! '>='
|
130
148
|
- !ruby/object:Gem::Version
|
131
149
|
version: '0'
|
132
150
|
type: :development
|
133
151
|
prerelease: false
|
134
152
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
135
154
|
requirements:
|
136
|
-
- -
|
155
|
+
- - ! '>='
|
137
156
|
- !ruby/object:Gem::Version
|
138
157
|
version: '0'
|
139
158
|
description: A gem for describing constraints on data sets
|
@@ -143,8 +162,8 @@ executables: []
|
|
143
162
|
extensions: []
|
144
163
|
extra_rdoc_files: []
|
145
164
|
files:
|
146
|
-
-
|
147
|
-
-
|
165
|
+
- .gitignore
|
166
|
+
- .travis.yml
|
148
167
|
- Gemfile
|
149
168
|
- MIT-LICENSE
|
150
169
|
- README.md
|
@@ -158,6 +177,7 @@ files:
|
|
158
177
|
- lib/set_builder/errors/trait_not_found.rb
|
159
178
|
- lib/set_builder/modifier.rb
|
160
179
|
- lib/set_builder/modifier/adverb.rb
|
180
|
+
- lib/set_builder/modifier/arguments.rb
|
161
181
|
- lib/set_builder/modifier/base.rb
|
162
182
|
- lib/set_builder/modifier/verb.rb
|
163
183
|
- lib/set_builder/modifier_collection.rb
|
@@ -165,6 +185,7 @@ files:
|
|
165
185
|
- lib/set_builder/modifiers/date_preposition.rb
|
166
186
|
- lib/set_builder/modifiers/number_preposition.rb
|
167
187
|
- lib/set_builder/modifiers/string_preposition.rb
|
188
|
+
- lib/set_builder/parser.rb
|
168
189
|
- lib/set_builder/set.rb
|
169
190
|
- lib/set_builder/trait.rb
|
170
191
|
- lib/set_builder/trait_builder.rb
|
@@ -209,26 +230,30 @@ files:
|
|
209
230
|
homepage: ''
|
210
231
|
licenses:
|
211
232
|
- MIT
|
212
|
-
metadata: {}
|
213
233
|
post_install_message:
|
214
234
|
rdoc_options: []
|
215
235
|
require_paths:
|
216
236
|
- lib
|
217
237
|
required_ruby_version: !ruby/object:Gem::Requirement
|
238
|
+
none: false
|
218
239
|
requirements:
|
219
|
-
- -
|
240
|
+
- - ! '>='
|
220
241
|
- !ruby/object:Gem::Version
|
221
242
|
version: '0'
|
243
|
+
segments:
|
244
|
+
- 0
|
245
|
+
hash: -2909033226206724461
|
222
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
+
none: false
|
223
248
|
requirements:
|
224
|
-
- -
|
249
|
+
- - ! '>'
|
225
250
|
- !ruby/object:Gem::Version
|
226
251
|
version: 1.3.1
|
227
252
|
requirements: []
|
228
253
|
rubyforge_project:
|
229
|
-
rubygems_version:
|
254
|
+
rubygems_version: 1.8.23.2
|
230
255
|
signing_key:
|
231
|
-
specification_version:
|
256
|
+
specification_version: 3
|
232
257
|
summary: Define traits on a model, create sets that constrain those traits, and generate
|
233
258
|
both natural-language descriptions of the sets and queries to select them
|
234
259
|
test_files:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: acd34d467c6aca8cc3c42db795261de035c72c58
|
4
|
-
data.tar.gz: 2c08cc3a703c5cc84230cbaa0e047004d4e7f430
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: d79aec9ff59f398bc844de87cbc9a7946fb43166017d1231c36fc8a1ff267a296a98e88e524d3b01b2c726bd91ed75d4e63833246e32cc6fa25114e038809cb1
|
7
|
-
data.tar.gz: d4ba5f0e2dfff5ad5245abd758adcac891c93fe2e0bba30c830e52b7dd63e7749962ed6843dc4f3c4b33b1e7b3a3b33dcb58ceef97312a417cce6abbf8be8962
|