set_builder 1.2.0.beta3 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -1
- data/lib/assets/javascripts/set_builder.js +80 -62
- data/lib/set_builder/constraint.rb +2 -2
- data/lib/set_builder/modifier.rb +12 -6
- data/lib/set_builder/modifiers/{date_modifier.rb → date_preposition.rb} +1 -1
- data/lib/set_builder/modifiers/{number_modifier.rb → number_preposition.rb} +2 -2
- data/lib/set_builder/modifiers/{string_modifier.rb → string_preposition.rb} +1 -1
- data/lib/set_builder/modifiers.rb +3 -3
- data/lib/set_builder/trait.rb +49 -47
- data/lib/set_builder/value_map.rb +8 -7
- data/lib/set_builder/version.rb +1 -1
- data/lib/set_builder.rb +6 -32
- data/set_builder.gemspec +3 -2
- data/spec/dom.html +2 -3
- data/spec/unit/array.spec.js +9 -1
- data/spec/unit/set_builder.spec.js +31 -21
- data/test/{date_modifier_test.rb → date_preposition_test.rb} +3 -3
- data/test/inflector_test.rb +6 -6
- data/test/modifier_test.rb +3 -3
- data/test/{string_modifier_test.rb → string_preposition_test.rb} +2 -2
- data/test/test_helper.rb +6 -13
- data/test/trait_test.rb +1 -1
- data/test/traits_test.rb +20 -7
- metadata +29 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33054edba058a15627aaf11cbdd32f2a3bdb5c7e
|
4
|
+
data.tar.gz: 2ab79d3204faa01c6acd43515f453d8c3a883990
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5af7ed922c28414483e4cf8c14704a94d527733a27ce8d07b95a3c687df7533594661c0d1099085d6326308602dd619dae2a143c09960aa69bdebdc41417b7e
|
7
|
+
data.tar.gz: 47f857f3f679dec0cb5f0c701bd45a890a8cdd968d9eb8a544d76c8e866bc8ddfb9c2747c7437b7dba845dd17c32ebed93f9f0ff759b8e0324564f00d16e4b45
|
data/README.md
CHANGED
@@ -27,5 +27,11 @@ SetBuilder can render this Set in plain English:
|
|
27
27
|
It can also generate a NamedScope on an ActiveRecord model to fetch the people who fit in this set.
|
28
28
|
|
29
29
|
|
30
|
+
### Running the tests
|
30
31
|
|
31
|
-
|
32
|
+
*Ruby* `bundle exec rake test`
|
33
|
+
|
34
|
+
*Javascript* `jspec run --browsers ff`
|
35
|
+
|
36
|
+
|
37
|
+
Copyright (c) 2010, 2015 Bob Lail, released under the MIT license
|
@@ -77,7 +77,7 @@ SetBuilder.Constraint = function(_trait, args) {
|
|
77
77
|
}
|
78
78
|
|
79
79
|
args = args.dup();
|
80
|
-
if(_trait.
|
80
|
+
if(_trait.requiresDirectObject()) _direct_object = args.shift();
|
81
81
|
var _modifiers = _trait.modifiers().collect(function(modifier_type) {
|
82
82
|
return SetBuilder.modifiers().apply(modifier_type, args.shift());
|
83
83
|
});
|
@@ -109,7 +109,7 @@ SetBuilder.Constraint = function(_trait, args) {
|
|
109
109
|
|
110
110
|
this.negate = function(value) {
|
111
111
|
_negative = value;
|
112
|
-
if(_trait.
|
112
|
+
if(!_trait.hasNegative()) _negative = false;
|
113
113
|
return this;
|
114
114
|
}
|
115
115
|
|
@@ -121,19 +121,26 @@ SetBuilder.Constraint = function(_trait, args) {
|
|
121
121
|
return _trait.requires_direct_object();
|
122
122
|
}
|
123
123
|
|
124
|
-
this.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
124
|
+
this.toString = function() {
|
125
|
+
var type, text, i = 0;
|
126
|
+
return _trait.tokens().collect(function(token) {
|
127
|
+
type = token[0], text = token[1];
|
128
|
+
switch(type) {
|
129
|
+
case 'string':
|
130
|
+
return text;
|
131
|
+
case 'name':
|
132
|
+
return _trait.name();
|
133
|
+
case 'negative':
|
134
|
+
return _negative && text;
|
135
|
+
case 'direct_object_type':
|
136
|
+
return SetBuilder.getValue(text, _direct_object);
|
137
|
+
case 'modifier':
|
138
|
+
return _modifiers[i++].toString();
|
139
|
+
default:
|
140
|
+
if(console && console.log) console.log('[SetBuilder.Constraint] unknown type: "' + type + '" (text: "' + text + '")');
|
141
|
+
return false;
|
142
|
+
}
|
143
|
+
}).compact().join(' ');
|
137
144
|
}
|
138
145
|
|
139
146
|
};
|
@@ -165,7 +172,7 @@ SetBuilder.Modifier = function(_name, _operator, _values, _params) {
|
|
165
172
|
return _values;
|
166
173
|
}
|
167
174
|
|
168
|
-
this.toString = function(
|
175
|
+
this.toString = function() {
|
169
176
|
var words = [_operator.replace(/_/, ' ')];
|
170
177
|
for(var i=0; i<_values.length; i++) {
|
171
178
|
words.push(SetBuilder.getValue(_params[i], _values[i]));
|
@@ -265,7 +272,6 @@ SetBuilder.Modifiers = function(_modifiers) {
|
|
265
272
|
*/
|
266
273
|
|
267
274
|
SetBuilder.Set = function(_raw_data) {
|
268
|
-
|
269
275
|
if(!_raw_data) _raw_data = [];
|
270
276
|
|
271
277
|
var _constraints = [];
|
@@ -314,27 +320,32 @@ SetBuilder.Set = function(_raw_data) {
|
|
314
320
|
an individual trait that can be constrained
|
315
321
|
*/
|
316
322
|
|
317
|
-
SetBuilder.Trait = function(
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
323
|
+
SetBuilder.Trait = function(_tokens) {
|
324
|
+
|
325
|
+
var type, text;
|
326
|
+
var _name, _modifiers = [], _direct_object_type, _negative;
|
327
|
+
_tokens.each(function(token) {
|
328
|
+
type = token[0], text = token[1];
|
329
|
+
switch(type) {
|
330
|
+
case 'name':
|
331
|
+
_name = text;
|
332
|
+
break;
|
333
|
+
case 'modifier':
|
334
|
+
_modifiers.push(text);
|
335
|
+
break;
|
336
|
+
case 'direct_object_type':
|
337
|
+
_direct_object_type = text;
|
338
|
+
break;
|
339
|
+
case 'negative':
|
340
|
+
_negative = text;
|
341
|
+
break;
|
342
|
+
}
|
343
|
+
});
|
333
344
|
|
334
345
|
|
335
346
|
// Public methods
|
336
347
|
|
337
|
-
this.
|
348
|
+
this.requiresDirectObject = function() {
|
338
349
|
return !!_direct_object_type;
|
339
350
|
}
|
340
351
|
|
@@ -346,39 +357,16 @@ SetBuilder.Trait = function(_raw_data) {
|
|
346
357
|
return _name;
|
347
358
|
}
|
348
359
|
|
349
|
-
this.
|
350
|
-
return
|
360
|
+
this.hasNegative = function() {
|
361
|
+
return !!_negative;
|
351
362
|
}
|
352
363
|
|
353
364
|
this.modifiers = function() {
|
354
365
|
return _modifiers;
|
355
366
|
}
|
356
367
|
|
357
|
-
this.
|
358
|
-
|
359
|
-
switch(_part_of_speech) {
|
360
|
-
case 'active':
|
361
|
-
return negative ? 'who have not' : 'who';
|
362
|
-
case 'perfect':
|
363
|
-
return negative ? 'who have not' : 'who have';
|
364
|
-
case 'passive':
|
365
|
-
return negative ? 'who were not' : 'who were';
|
366
|
-
case 'reflexive':
|
367
|
-
return negative ? 'who are not' : 'who are';
|
368
|
-
case 'noun':
|
369
|
-
return 'whose';
|
370
|
-
default:
|
371
|
-
return undefined;
|
372
|
-
}
|
373
|
-
}
|
374
|
-
|
375
|
-
this.toString = function(include_prefix, negative) {
|
376
|
-
var prefix = this.prefix(negative);
|
377
|
-
if(prefix) { // return an empty string if the prefix is invalid
|
378
|
-
return (include_prefix==false) ? this.name() : (prefix + ' ' + this.name());
|
379
|
-
} else {
|
380
|
-
return '';
|
381
|
-
}
|
368
|
+
this.tokens = function() {
|
369
|
+
return _tokens;
|
382
370
|
}
|
383
371
|
|
384
372
|
this.apply = function(args) {
|
@@ -397,7 +385,7 @@ SetBuilder.Trait = function(_raw_data) {
|
|
397
385
|
*/
|
398
386
|
|
399
387
|
SetBuilder.Traits = function(_raw_data) {
|
400
|
-
|
388
|
+
|
401
389
|
var _traits = _raw_data.collect(function(line) {
|
402
390
|
return new SetBuilder.Trait(line);
|
403
391
|
});
|
@@ -515,6 +503,22 @@ if(!Array.prototype.inject) Array.prototype.inject = Array.prototype.__inject;
|
|
515
503
|
|
516
504
|
|
517
505
|
|
506
|
+
//
|
507
|
+
// .compact
|
508
|
+
//
|
509
|
+
Array.prototype.__compact = function() {
|
510
|
+
var new_array = [];
|
511
|
+
for(var i=0; i<this.length; i++) {
|
512
|
+
if(this[i]) {
|
513
|
+
new_array.push(this[i]);
|
514
|
+
}
|
515
|
+
}
|
516
|
+
return new_array;
|
517
|
+
}
|
518
|
+
if(!Array.prototype.compact) Array.prototype.compact = Array.prototype.__compact;
|
519
|
+
|
520
|
+
|
521
|
+
|
518
522
|
//
|
519
523
|
// .find
|
520
524
|
//
|
@@ -527,3 +531,17 @@ Array.prototype.__find = function(fn) {
|
|
527
531
|
return null;
|
528
532
|
}
|
529
533
|
if(!Array.prototype.find) Array.prototype.find = Array.prototype.__find;
|
534
|
+
|
535
|
+
//
|
536
|
+
// .select
|
537
|
+
//
|
538
|
+
Array.prototype.__select = function(fn) {
|
539
|
+
var results = [];
|
540
|
+
for(var i=0; i<this.length; i++) {
|
541
|
+
if(fn(this[i])) {
|
542
|
+
results.push(this[i]);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
return results;
|
546
|
+
}
|
547
|
+
if(!Array.prototype.select) Array.prototype.select = Array.prototype.__select;
|
data/lib/set_builder/modifier.rb
CHANGED
@@ -33,8 +33,14 @@ module SetBuilder
|
|
33
33
|
|
34
34
|
|
35
35
|
|
36
|
-
def self.[](
|
37
|
-
|
36
|
+
def self.[](klassname_or_symbol)
|
37
|
+
is_classname = /^[A-Z]/.match(klassname_or_symbol)
|
38
|
+
if is_classname
|
39
|
+
klass = SetBuilder::Modifiers.const_get("#{klassname_or_symbol}")
|
40
|
+
SetBuilder::Modifier.valid_modifier!(klass)
|
41
|
+
else
|
42
|
+
SetBuilder::Modifier.for(klassname_or_symbol.to_sym)
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
|
@@ -98,9 +104,9 @@ module SetBuilder
|
|
98
104
|
# Force predefined modifiers to pass `valid_modifier?`
|
99
105
|
#
|
100
106
|
Modifier.register(
|
101
|
-
[:date, Modifiers::
|
102
|
-
[:number, Modifiers::
|
103
|
-
[:string, Modifiers::
|
107
|
+
[:date, Modifiers::DatePreposition],
|
108
|
+
[:number, Modifiers::NumberPreposition],
|
109
|
+
[:string, Modifiers::StringPreposition]
|
104
110
|
)
|
105
111
|
|
106
112
|
|
@@ -131,4 +137,4 @@ end
|
|
131
137
|
#
|
132
138
|
#
|
133
139
|
#
|
134
|
-
# end
|
140
|
+
# end
|
@@ -3,7 +3,7 @@ require 'set_builder/modifier/verb'
|
|
3
3
|
|
4
4
|
module SetBuilder
|
5
5
|
module Modifiers
|
6
|
-
class
|
6
|
+
class NumberPreposition < Modifier::Verb
|
7
7
|
|
8
8
|
|
9
9
|
|
@@ -42,7 +42,7 @@ module SetBuilder
|
|
42
42
|
when :is_greater_than
|
43
43
|
selector.gt(value)
|
44
44
|
when :is_between
|
45
|
-
selector.gteq(
|
45
|
+
selector.gteq(values[0]).and(selector.lteq(values[1]))
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -1,3 +1,3 @@
|
|
1
|
-
require 'set_builder/modifiers/
|
2
|
-
require 'set_builder/modifiers/
|
3
|
-
require 'set_builder/modifiers/
|
1
|
+
require 'set_builder/modifiers/string_preposition'
|
2
|
+
require 'set_builder/modifiers/date_preposition'
|
3
|
+
require 'set_builder/modifiers/number_preposition'
|
data/lib/set_builder/trait.rb
CHANGED
@@ -5,70 +5,72 @@ require 'set_builder/modifier'
|
|
5
5
|
module SetBuilder
|
6
6
|
class Trait
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
8
|
+
attr_reader :name, :parsed_expression, :part_of_speech, :modifiers, :direct_object_type
|
9
|
+
|
10
|
+
LEXER = {
|
11
|
+
name: /("[^"]+")/,
|
12
|
+
direct_object_type: /(:\w+)/,
|
13
|
+
negative: /(\[[^\]]+\])/,
|
14
|
+
modifier: /(<\w+>)/
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def initialize(trait_expression, &block)
|
18
|
+
@parsed_expression = parse(trait_expression)
|
19
|
+
@name, @direct_object_type = find(:name), find(:direct_object_type)
|
20
|
+
@block = block
|
21
|
+
@modifiers = find_all(:modifier).map { |modifier| Modifier[modifier] }
|
19
22
|
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
attr_reader :name, :part_of_speech, :modifiers, :direct_object_type
|
24
|
-
|
25
|
-
|
26
|
-
|
27
24
|
def requires_direct_object?
|
28
25
|
!@direct_object_type.nil?
|
29
26
|
end
|
30
27
|
alias :direct_object_required? :requires_direct_object?
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
def noun?
|
35
|
-
(self.part_of_speech == :noun)
|
29
|
+
def negative?
|
30
|
+
find(:negative)
|
36
31
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
|
40
33
|
def to_s(negative=false)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
when :passive
|
47
|
-
negative ? "who were not #{name}" : "who were #{name}"
|
48
|
-
when :reflexive
|
49
|
-
negative ? "who are not #{name}" : "who are #{name}"
|
50
|
-
when :noun
|
51
|
-
"whose #{name}"
|
52
|
-
end
|
34
|
+
parsed_expression.reject do |token, _|
|
35
|
+
[:modifier, :direct_object_type].include?(token) || (!negative && token == :negative)
|
36
|
+
end.map do |token, value|
|
37
|
+
token == :name ? name : value
|
38
|
+
end.join(" ")
|
53
39
|
end
|
54
40
|
|
55
|
-
|
56
|
-
|
57
|
-
def to_json
|
58
|
-
array = []
|
59
|
-
array << (requires_direct_object? ? [name, @direct_object_type] : name)
|
60
|
-
array << part_of_speech
|
61
|
-
array << modifiers.collect{|klass| Modifier.name(klass)} unless modifiers.empty?
|
62
|
-
array.to_json
|
41
|
+
def find_all(token)
|
42
|
+
parsed_expression.select { |(_token, _)| _token == token }.map { |(_, value)| value }
|
63
43
|
end
|
64
44
|
|
45
|
+
def find(token)
|
46
|
+
find_all(token).first
|
47
|
+
end
|
65
48
|
|
66
|
-
|
49
|
+
def as_json(*)
|
50
|
+
parsed_expression.map { |(token, value)| [token.to_s, value] }
|
51
|
+
end
|
52
|
+
|
67
53
|
def apply(*args)
|
68
54
|
SetBuilder::Constraint.new(self, *args, &@block)
|
69
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def parse(trait_definition)
|
60
|
+
regex = Regexp.union(LEXER.values)
|
61
|
+
trait_definition.split(regex).map do |lexeme|
|
62
|
+
[token_for(lexeme), value_for(lexeme)] unless lexeme.strip.empty?
|
63
|
+
end.compact
|
64
|
+
end
|
70
65
|
|
66
|
+
def token_for(lexeme)
|
67
|
+
LEXER.each { |token, pattern| return token if pattern.match(lexeme) }
|
68
|
+
return :string
|
69
|
+
end
|
71
70
|
|
72
|
-
|
71
|
+
def value_for(lexeme)
|
72
|
+
lexeme.to_s.strip.gsub(/[<>"\[\]:]/, "")
|
73
|
+
end
|
74
|
+
|
73
75
|
end
|
74
|
-
end
|
76
|
+
end
|
@@ -16,14 +16,15 @@ module SetBuilder
|
|
16
16
|
|
17
17
|
def self.to_s(name, value)
|
18
18
|
if value.is_a?(Array)
|
19
|
-
values = value.map { |value|
|
20
|
-
|
21
|
-
when 0
|
22
|
-
when 1
|
23
|
-
when 2
|
24
|
-
else
|
19
|
+
values = value.map { |value| to_s(name, value) }
|
20
|
+
case value.length
|
21
|
+
when 0 then return ""
|
22
|
+
when 1 then return values.first
|
23
|
+
when 2 then return "#{values.first} or #{values.last}"
|
24
|
+
else return "#{values[0..-2].join(', ')}, or #{values.last}"
|
25
25
|
end
|
26
26
|
end
|
27
|
+
|
27
28
|
name = name.to_sym
|
28
29
|
map = @registered_value_maps[name]
|
29
30
|
if map
|
@@ -44,7 +45,7 @@ module SetBuilder
|
|
44
45
|
|
45
46
|
|
46
47
|
def self.register_collection(name, collection, name_method = :name, id_method = :id)
|
47
|
-
map = collection.map {|i| [i.send(id_method).to_s, i.send(name_method)]}
|
48
|
+
map = collection.map { |i| [i.send(id_method).to_s, i.send(name_method)] }
|
48
49
|
register(name, map)
|
49
50
|
end
|
50
51
|
|
data/lib/set_builder/version.rb
CHANGED
data/lib/set_builder.rb
CHANGED
@@ -8,8 +8,7 @@ require 'set_builder/engine'
|
|
8
8
|
|
9
9
|
|
10
10
|
module SetBuilder
|
11
|
-
|
12
|
-
|
11
|
+
|
13
12
|
def self.extended(base)
|
14
13
|
base.instance_variable_set("@traits", SetBuilder::Traits.new)
|
15
14
|
base.send(:include, SetBuilder::Modifiers)
|
@@ -18,47 +17,22 @@ module SetBuilder
|
|
18
17
|
|
19
18
|
attr_reader :traits
|
20
19
|
|
21
|
-
|
22
20
|
def modifiers
|
23
21
|
traits.modifiers
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
24
|
def that_belong_to(set)
|
28
25
|
SetBuilder::Set.new(self, to_scope, set)
|
29
26
|
end
|
30
27
|
|
31
|
-
|
32
28
|
def to_scope
|
33
29
|
scoped
|
34
30
|
end
|
35
|
-
|
36
|
-
|
31
|
+
|
37
32
|
protected
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def trait(*args, &block)
|
42
|
-
part_of_speech = get_part_of_speech(args.shift)
|
43
|
-
name = args.shift
|
44
|
-
traits << Trait.new(name, part_of_speech, *args, &block)
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
def get_part_of_speech(arg)
|
49
|
-
case arg
|
50
|
-
when :is, :are, :reflexive
|
51
|
-
:reflexive
|
52
|
-
when nil, :active
|
53
|
-
:active
|
54
|
-
when :was, :were, :passive
|
55
|
-
:passive
|
56
|
-
when :has, :have, :perfect
|
57
|
-
:perfect
|
58
|
-
when :whose, :noun
|
59
|
-
:noun
|
60
|
-
end
|
33
|
+
|
34
|
+
def trait(trait_expression, &block)
|
35
|
+
traits << Trait.new(trait_expression, &block)
|
61
36
|
end
|
62
37
|
|
63
|
-
|
64
|
-
end
|
38
|
+
end
|
data/set_builder.gemspec
CHANGED
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "rails", ">= 3.1", "<
|
22
|
-
spec.add_dependency "arel"
|
21
|
+
spec.add_dependency "rails", ">= 3.1", "< 4.2"
|
22
|
+
spec.add_dependency "arel"
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
24
|
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "jspec"
|
25
26
|
spec.add_development_dependency "pry"
|
26
27
|
end
|
data/spec/dom.html
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
<link type="text/css" rel="stylesheet" href="./lib/jspec.css" />
|
4
4
|
<script src="./lib/jspec.js"></script>
|
5
5
|
<script src="./lib/jspec.xhr.js"></script>
|
6
|
-
<script src="../assets/
|
7
|
-
<script src="../assets/set_builder.js"></script>
|
6
|
+
<script src="../lib/assets/javascripts/set_builder.js"></script>
|
8
7
|
<script src="unit/spec.helper.js"></script>
|
9
8
|
<script>
|
10
9
|
function runSuites() {
|
@@ -21,4 +20,4 @@
|
|
21
20
|
<div id="jspec"></div>
|
22
21
|
<div id="jspec-bottom"></div>
|
23
22
|
</body>
|
24
|
-
</html>
|
23
|
+
</html>
|
data/spec/unit/array.spec.js
CHANGED
@@ -66,6 +66,14 @@ describe 'Array'
|
|
66
66
|
})).to(be, "what?")
|
67
67
|
end
|
68
68
|
end
|
69
|
+
|
70
|
+
describe '.select'
|
71
|
+
it 'should return all members of the array where fn(member) is true'
|
72
|
+
expect(["this", "nope", "that", "this"].select(function(word){
|
73
|
+
return word == "this";
|
74
|
+
})).to(eql, ["this", "this"]);
|
75
|
+
end
|
76
|
+
end
|
69
77
|
|
70
78
|
end
|
71
79
|
|
@@ -79,4 +87,4 @@ describe 'Object'
|
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
82
|
-
end
|
90
|
+
end
|
@@ -2,11 +2,25 @@ describe 'SetBuilder'
|
|
2
2
|
before_each
|
3
3
|
|
4
4
|
SetBuilder.registerTraits([
|
5
|
-
['
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
[['string','who are'],
|
6
|
+
['negative','not'],
|
7
|
+
['name','awesome']],
|
8
|
+
[['string','who'],
|
9
|
+
['negative','have not'],
|
10
|
+
['name','died']],
|
11
|
+
[['string','who were'],
|
12
|
+
['name','born'],
|
13
|
+
['modifier','date']],
|
14
|
+
[['string','whose'],
|
15
|
+
['name','age'],
|
16
|
+
['modifier','number']],
|
17
|
+
[['string','who have'],
|
18
|
+
['negative','not'],
|
19
|
+
['name','attended'],
|
20
|
+
['direct_object_type','school']],
|
21
|
+
[['string','whose'],
|
22
|
+
['name','name'],
|
23
|
+
['modifier','string']]
|
10
24
|
]);
|
11
25
|
|
12
26
|
SetBuilder.registerModifiers({
|
@@ -59,23 +73,19 @@ describe 'SetBuilder'
|
|
59
73
|
describe '.Trait'
|
60
74
|
|
61
75
|
describe '.constructor'
|
62
|
-
it 'should correctly parse
|
63
|
-
var trait = new SetBuilder.Trait(['
|
76
|
+
it 'should correctly parse the name of the trait'
|
77
|
+
var trait = new SetBuilder.Trait([['string', 'who are'], ['name', 'awesome']]);
|
64
78
|
expect(trait.name()).to(be, 'awesome');
|
65
|
-
expect(trait.toString()).to(eql, 'who are awesome');
|
66
79
|
end
|
67
80
|
|
68
|
-
it 'should correctly identify direct objects'
|
69
|
-
var trait = new SetBuilder.Trait([['
|
70
|
-
expect(trait.
|
71
|
-
expect(trait.requires_direct_object()).to(be, true);
|
72
|
-
expect(trait.toString()).to(eql, 'who have attended');
|
81
|
+
it 'should correctly identify when it expects a direct objects'
|
82
|
+
var trait = new SetBuilder.Trait([['string', 'who have'], ['name', 'attended'], ['direct_object_type', 'string']]);
|
83
|
+
expect(trait.requiresDirectObject()).to(be, true);
|
73
84
|
end
|
74
85
|
|
75
86
|
it 'should correctly parse paramters with modifiers'
|
76
|
-
var trait = new SetBuilder.Trait(['
|
87
|
+
var trait = new SetBuilder.Trait([['string', 'who were'], ['name', 'born'], ['modifier', 'date']]);
|
77
88
|
expect(trait.modifiers().length).to(be, 1);
|
78
|
-
expect(trait.toString()).to(eql, 'who were born');
|
79
89
|
end
|
80
90
|
end
|
81
91
|
|
@@ -90,17 +100,17 @@ describe 'SetBuilder'
|
|
90
100
|
|
91
101
|
describe '.length'
|
92
102
|
it 'should have parsed the data structure correctly'
|
93
|
-
expect(traits.length()).to(be,
|
103
|
+
expect(traits.length()).to(be, 6);
|
94
104
|
end
|
95
105
|
end
|
96
106
|
|
97
107
|
describe '.find'
|
98
108
|
it 'should get a SetBuilder.Trait object by name'
|
99
|
-
expect(traits.__find('awesome').
|
100
|
-
expect(traits.__find('died').
|
101
|
-
expect(traits.__find('born').
|
102
|
-
expect(traits.__find('attended').
|
103
|
-
expect(traits.__find('name').
|
109
|
+
expect(traits.__find('awesome').name()).to(eql, 'awesome');
|
110
|
+
expect(traits.__find('died').name()).to(eql, 'died');
|
111
|
+
expect(traits.__find('born').name()).to(eql, 'born');
|
112
|
+
expect(traits.__find('attended').name()).to(eql,'attended');
|
113
|
+
expect(traits.__find('name').name()).to(eql, 'name');
|
104
114
|
end
|
105
115
|
end
|
106
116
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class DatePrepositionTest < ActiveSupport::TestCase
|
4
4
|
include SetBuilder::Modifiers
|
5
5
|
|
6
6
|
|
7
7
|
test "should constrain our date queries to A.D." do
|
8
|
-
modifier =
|
8
|
+
modifier = DatePreposition.new({:in_the_last => [Date.today.year, "years"]})
|
9
9
|
assert_equal "x>='0001-01-01'", modifier.build_conditions_for("x")
|
10
10
|
end
|
11
11
|
|
12
12
|
|
13
|
-
end
|
13
|
+
end
|
data/test/inflector_test.rb
CHANGED
@@ -4,24 +4,24 @@ class InflectorTest < ActiveSupport::TestCase
|
|
4
4
|
|
5
5
|
|
6
6
|
test "active" do
|
7
|
-
assert_equal "who died", SetBuilder::Trait.new("died"
|
7
|
+
assert_equal "who died", SetBuilder::Trait.new('who "died"').to_s
|
8
8
|
end
|
9
9
|
|
10
10
|
test "perfect" do
|
11
|
-
assert_equal "who have attended", SetBuilder::Trait.new("attended"
|
11
|
+
assert_equal "who have attended", SetBuilder::Trait.new('who have "attended"').to_s
|
12
12
|
end
|
13
13
|
|
14
14
|
test "passive" do
|
15
|
-
assert_equal "who were born", SetBuilder::Trait.new("born"
|
15
|
+
assert_equal "who were born", SetBuilder::Trait.new('who were "born"').to_s
|
16
16
|
end
|
17
17
|
|
18
18
|
test "reflexive" do
|
19
|
-
assert_equal "who are awesome", SetBuilder::Trait.new("awesome"
|
19
|
+
assert_equal "who are awesome", SetBuilder::Trait.new('who are "awesome"').to_s
|
20
20
|
end
|
21
21
|
|
22
22
|
test "noun" do
|
23
|
-
assert_equal "whose name", SetBuilder::Trait.new("name"
|
23
|
+
assert_equal "whose name", SetBuilder::Trait.new('whose "name"').to_s
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
|
-
end
|
27
|
+
end
|
data/test/modifier_test.rb
CHANGED
@@ -5,11 +5,11 @@ class ModifierTest < ActiveSupport::TestCase
|
|
5
5
|
|
6
6
|
|
7
7
|
test "get type with string" do
|
8
|
-
assert_equal
|
8
|
+
assert_equal StringPreposition, SetBuilder::Modifier["StringPreposition"]
|
9
9
|
end
|
10
10
|
|
11
11
|
test "get type with symbol" do
|
12
|
-
assert_equal
|
12
|
+
assert_equal StringPreposition, SetBuilder::Modifier[:string]
|
13
13
|
end
|
14
14
|
|
15
15
|
test "registering a modifier" do
|
@@ -87,4 +87,4 @@ class HashModifier < SetBuilder::Modifier::Verb
|
|
87
87
|
[:has_key]
|
88
88
|
end
|
89
89
|
|
90
|
-
end
|
90
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class StringPrepositionTest < ActiveSupport::TestCase
|
4
4
|
include SetBuilder::Modifiers
|
5
5
|
|
6
6
|
attr_reader :table
|
@@ -11,7 +11,7 @@ class StringModifierTest < ActiveSupport::TestCase
|
|
11
11
|
|
12
12
|
|
13
13
|
test "#build_arel_for should generate the correct SQL" do
|
14
|
-
modifier =
|
14
|
+
modifier = StringPreposition.new({:does_not_contain => ["banana"]})
|
15
15
|
assert_equal "\"fruits\".\"name\" NOT LIKE '%banana%'", modifier.build_arel_for(table[:name]).to_sql
|
16
16
|
end
|
17
17
|
|
data/test/test_helper.rb
CHANGED
@@ -15,40 +15,33 @@ SetBuilder::ValueMap.register(:school, [[1, "Concordia"], [2, "McKendree"]])
|
|
15
15
|
class Friend
|
16
16
|
extend SetBuilder
|
17
17
|
|
18
|
-
|
19
|
-
trait(:is, "awesome") do |query, scope|
|
18
|
+
trait('who are [not] "awesome"') do |query, scope|
|
20
19
|
scope << {:conditions => {:awesome => true}}
|
21
20
|
end
|
22
21
|
|
23
|
-
trait(
|
22
|
+
trait('who [have not] "died"') do |query, scope|
|
24
23
|
scope << {:conditions => {:alive => false}}
|
25
24
|
end
|
26
25
|
|
27
|
-
|
28
|
-
trait(:was, "born", :date) do |query, scope|
|
26
|
+
trait('who were "born" <date>') do |query, scope|
|
29
27
|
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.birthday")}
|
30
28
|
end
|
31
29
|
|
32
|
-
trait(
|
30
|
+
trait('whose "age" <number>') do |query, scope|
|
33
31
|
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.age")}
|
34
32
|
end
|
35
33
|
|
36
|
-
|
37
|
-
trait(:has, {"attended" => :school}) do |query, scope|
|
34
|
+
trait('who have [not] "attended" :school') do |query, scope|
|
38
35
|
scope << {
|
39
36
|
:joins => "INNER JOIN schools ON friends.school_id=schools.id",
|
40
37
|
:conditions => {"schools.id" => query.direct_object}
|
41
38
|
}
|
42
39
|
end
|
43
40
|
|
44
|
-
|
45
|
-
# also modifiers can be classes
|
46
|
-
trait(:whose, "name", StringModifier) do |query, scope|
|
41
|
+
trait('whose "name" <string>') do |query, scope|
|
47
42
|
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.name")}
|
48
43
|
end
|
49
44
|
|
50
|
-
|
51
|
-
|
52
45
|
# by stubbing out scoped, we can unit test the `performed` features
|
53
46
|
def self.to_scope
|
54
47
|
[]
|
data/test/trait_test.rb
CHANGED
@@ -10,7 +10,7 @@ class TraitTest < ActiveSupport::TestCase
|
|
10
10
|
|
11
11
|
constraint = trait.apply({:is => "Jerome"})
|
12
12
|
assert_equal 1, constraint.modifiers.length
|
13
|
-
assert_kind_of
|
13
|
+
assert_kind_of StringPreposition, constraint.modifiers.first
|
14
14
|
end
|
15
15
|
|
16
16
|
test "modifiers should find correct values" do
|
data/test/traits_test.rb
CHANGED
@@ -23,17 +23,30 @@ class TraitsTest < ActiveSupport::TestCase
|
|
23
23
|
end
|
24
24
|
|
25
25
|
test "collection of modifiers" do
|
26
|
-
expected_modifiers = %w{
|
26
|
+
expected_modifiers = %w{DatePreposition NumberPreposition StringPreposition}.collect {|name| "SetBuilder::Modifiers::#{name}"}
|
27
27
|
assert_equal expected_modifiers, Friend.traits.modifiers.collect(&:name).sort
|
28
28
|
end
|
29
29
|
|
30
30
|
test "to_json" do
|
31
|
-
expected_json = [[
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
expected_json = [[["string","who are"],
|
32
|
+
["negative","not"],
|
33
|
+
["name","awesome"]],
|
34
|
+
[["string","who"],
|
35
|
+
["negative","have not"],
|
36
|
+
["name","died"]],
|
37
|
+
[["string","who were"],
|
38
|
+
["name","born"],
|
39
|
+
["modifier","date"]],
|
40
|
+
[["string","whose"],
|
41
|
+
["name","age"],
|
42
|
+
["modifier","number"]],
|
43
|
+
[["string","who have"],
|
44
|
+
["negative","not"],
|
45
|
+
["name","attended"],
|
46
|
+
["direct_object_type","school"]],
|
47
|
+
[["string","whose"],
|
48
|
+
["name","name"],
|
49
|
+
["modifier","string"]]].to_json
|
37
50
|
assert_equal expected_json, Friend.traits.to_json
|
38
51
|
end
|
39
52
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: set_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '3.1'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '4.2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,21 +29,21 @@ dependencies:
|
|
29
29
|
version: '3.1'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '4.2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: arel
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '0'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: jspec
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: pry
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,9 +125,9 @@ files:
|
|
111
125
|
- lib/set_builder/modifier/verb.rb
|
112
126
|
- lib/set_builder/modifier_collection.rb
|
113
127
|
- lib/set_builder/modifiers.rb
|
114
|
-
- lib/set_builder/modifiers/
|
115
|
-
- lib/set_builder/modifiers/
|
116
|
-
- lib/set_builder/modifiers/
|
128
|
+
- lib/set_builder/modifiers/date_preposition.rb
|
129
|
+
- lib/set_builder/modifiers/number_preposition.rb
|
130
|
+
- lib/set_builder/modifiers/string_preposition.rb
|
117
131
|
- lib/set_builder/query_builders/string.rb
|
118
132
|
- lib/set_builder/set.rb
|
119
133
|
- lib/set_builder/trait.rb
|
@@ -144,11 +158,11 @@ files:
|
|
144
158
|
- spec/unit/array.spec.js
|
145
159
|
- spec/unit/set_builder.spec.js
|
146
160
|
- spec/unit/spec.helper.js
|
147
|
-
- test/
|
161
|
+
- test/date_preposition_test.rb
|
148
162
|
- test/inflector_test.rb
|
149
163
|
- test/modifier_test.rb
|
150
164
|
- test/set_test.rb
|
151
|
-
- test/
|
165
|
+
- test/string_preposition_test.rb
|
152
166
|
- test/support/fake_connection.rb
|
153
167
|
- test/test_helper.rb
|
154
168
|
- test/trait_test.rb
|
@@ -204,11 +218,11 @@ test_files:
|
|
204
218
|
- spec/unit/array.spec.js
|
205
219
|
- spec/unit/set_builder.spec.js
|
206
220
|
- spec/unit/spec.helper.js
|
207
|
-
- test/
|
221
|
+
- test/date_preposition_test.rb
|
208
222
|
- test/inflector_test.rb
|
209
223
|
- test/modifier_test.rb
|
210
224
|
- test/set_test.rb
|
211
|
-
- test/
|
225
|
+
- test/string_preposition_test.rb
|
212
226
|
- test/support/fake_connection.rb
|
213
227
|
- test/test_helper.rb
|
214
228
|
- test/trait_test.rb
|