set_builder 1.0.2

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +35 -0
  6. data/Rakefile +14 -0
  7. data/assets/javascripts/array.js +100 -0
  8. data/assets/javascripts/set_builder.js +415 -0
  9. data/init.rb +1 -0
  10. data/install.rb +1 -0
  11. data/lib/set_builder.rb +58 -0
  12. data/lib/set_builder/constraint.rb +67 -0
  13. data/lib/set_builder/modifier.rb +134 -0
  14. data/lib/set_builder/modifier/adverb.rb +11 -0
  15. data/lib/set_builder/modifier/base.rb +105 -0
  16. data/lib/set_builder/modifier/verb.rb +24 -0
  17. data/lib/set_builder/modifier_collection.rb +41 -0
  18. data/lib/set_builder/modifiers.rb +3 -0
  19. data/lib/set_builder/modifiers/date_modifier.rb +83 -0
  20. data/lib/set_builder/modifiers/number_modifier.rb +48 -0
  21. data/lib/set_builder/modifiers/string_modifier.rb +81 -0
  22. data/lib/set_builder/query_builders/string.rb +0 -0
  23. data/lib/set_builder/set.rb +81 -0
  24. data/lib/set_builder/trait.rb +74 -0
  25. data/lib/set_builder/traits.rb +42 -0
  26. data/lib/set_builder/value_map.rb +62 -0
  27. data/lib/set_builder/version.rb +3 -0
  28. data/set_builder.gemspec +25 -0
  29. data/spec/commands/example_command.rb +19 -0
  30. data/spec/dom.html +24 -0
  31. data/spec/lib/images/bg.png +0 -0
  32. data/spec/lib/images/hr.png +0 -0
  33. data/spec/lib/images/loading.gif +0 -0
  34. data/spec/lib/images/sprites.bg.png +0 -0
  35. data/spec/lib/images/sprites.png +0 -0
  36. data/spec/lib/images/vr.png +0 -0
  37. data/spec/lib/jspec.css +149 -0
  38. data/spec/lib/jspec.growl.js +115 -0
  39. data/spec/lib/jspec.jquery.js +88 -0
  40. data/spec/lib/jspec.js +1908 -0
  41. data/spec/lib/jspec.nodejs.js +18 -0
  42. data/spec/lib/jspec.shell.js +39 -0
  43. data/spec/lib/jspec.timers.js +154 -0
  44. data/spec/lib/jspec.xhr.js +210 -0
  45. data/spec/node.js +10 -0
  46. data/spec/rhino.js +10 -0
  47. data/spec/server.html +18 -0
  48. data/spec/server.rb +4 -0
  49. data/spec/unit/array.spec.js +82 -0
  50. data/spec/unit/set_builder.spec.js +166 -0
  51. data/spec/unit/spec.helper.js +0 -0
  52. data/test/date_modifier_test.rb +13 -0
  53. data/test/inflector_test.rb +27 -0
  54. data/test/modifier_test.rb +90 -0
  55. data/test/set_test.rb +96 -0
  56. data/test/test_helper.rb +79 -0
  57. data/test/trait_test.rb +49 -0
  58. data/test/traits_test.rb +41 -0
  59. data/test/value_map_test.rb +30 -0
  60. data/uninstall.rb +1 -0
  61. metadata +191 -0
data/spec/server.html ADDED
@@ -0,0 +1,18 @@
1
+ <html>
2
+ <head>
3
+ <script src="/jspec/jspec.js"></script>
4
+ <script src="/jspec/jspec.xhr.js"></script>
5
+ <script src="/assets/set_builder.js"></script>
6
+ <script src="/spec/unit/spec.helper.js"></script>
7
+ <script>
8
+ function runSuites() {
9
+ JSpec
10
+ .exec('unit/spec.js')
11
+ .run({ reporter: JSpec.reporters.Server, verbose: true, failuresOnly: true, fixturePath: '/spec/fixtures' })
12
+ .report()
13
+ }
14
+ </script>
15
+ </head>
16
+ <body class="jspec" onLoad="runSuites();">
17
+ </body>
18
+ </html>
data/spec/server.rb ADDED
@@ -0,0 +1,4 @@
1
+
2
+ get '/lib/*' do |path|
3
+ send_file File.dirname(__FILE__) + '/../lib/' + path
4
+ end
@@ -0,0 +1,82 @@
1
+ describe 'Array'
2
+
3
+ describe '.toSentence'
4
+ it 'should return an empty string if you pass a 0-length array'
5
+ expect([].toSentence()).to(be, '');
6
+ end
7
+
8
+ it 'should return the lone value if you pass a 1-length array'
9
+ expect(['banana'].toSentence()).to(be, 'banana');
10
+ end
11
+
12
+ it 'should concatenate only using "and" if you pass a 2-length array'
13
+ expect(['apple', 'banana'].toSentence()).to(be, 'apple and banana');
14
+ end
15
+
16
+ it 'should use different concatenators for a 3+-length array'
17
+ expect(['apple', 'banana', 'chocolate'].toSentence()).to(be, 'apple, banana, and chocolate');
18
+ end
19
+ end
20
+
21
+ describe '.dup'
22
+ it 'should create an independently modifiable array'
23
+ var a = [1, 2, 3];
24
+ var b = a.dup();
25
+ a.shift();
26
+ expect(a.length).to(be, 2);
27
+ expect(b.length).to(be, 3);
28
+ end
29
+ end
30
+
31
+ describe '.each'
32
+ it 'should correctly work through this array of arrays'
33
+ var i = 0;
34
+ [
35
+ ['awesome'],
36
+ ['attended', "school"],
37
+ ['died'],
38
+ ['name', {'is': "Jerome"}]
39
+ ].each(function(item) {
40
+ i += 1;
41
+ });
42
+ expect(i).to(be, 4);
43
+ end
44
+ end
45
+
46
+ describe '.inject'
47
+ it 'should count 4 objects in [12,32,12,11]'
48
+ expect([12,32,12,11].inject(0, function(i, item) {
49
+ return i + 1;
50
+ })).to(be, 4);
51
+ end
52
+ end
53
+
54
+ describe '.collect'
55
+ it 'should make each word lowercase in ["BIG", "ANGRY", "WORDS"]'
56
+ expect(["BIG", "ANGRY", "WORDS"].collect(function(word) {
57
+ return word.toLowerCase();
58
+ })).to(eql, ["big", "angry", "words"]);
59
+ end
60
+ end
61
+
62
+ describe '.find'
63
+ it 'should return the first word with an "a" in it'
64
+ expect(["not", "me", "what?", "me"].find(function(word) {
65
+ return /a/i.test(word);
66
+ })).to(be, "what?")
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+
73
+
74
+ describe 'Object'
75
+
76
+ describe '.keys'
77
+ it 'should return the properties of a JSON object'
78
+ expect(Object.keys({one:1, test:2, contains:'hi'})).to(eql, ['one', 'test', 'contains']);
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,166 @@
1
+ describe 'SetBuilder'
2
+ before_each
3
+
4
+ SetBuilder.registerTraits([
5
+ ['awesome', 'reflexive'],
6
+ ['died', 'active'],
7
+ ['born', 'passive', ['date']],
8
+ [['attended', 'school'], 'perfect'],
9
+ ['name', 'noun', ['string']]
10
+ ]);
11
+
12
+ SetBuilder.registerModifiers({
13
+ string: {
14
+ contains: ['string'],
15
+ begins_with: ['string'],
16
+ ends_with: ['string'],
17
+ is: ['string']
18
+ }
19
+ });
20
+
21
+ SetBuilder.registerValueMap('school', [['1','Concordia'], ['2','McKendree']]);
22
+
23
+ set_data = [
24
+ ['awesome'],
25
+ ['attended', 2],
26
+ ['died'],
27
+ ['name', {'is': "Jerome"}]
28
+ ];
29
+ end
30
+
31
+
32
+
33
+
34
+ describe '.getValueMap'
35
+ it 'should return an array of arrays'
36
+ expect(SetBuilder.getValueMap('school')).to(eql, [['1','Concordia'], ['2','McKendree']]);
37
+ end
38
+ end
39
+
40
+ describe '.getValue'
41
+ it 'should return a value based on the key and name'
42
+ expect(SetBuilder.getValue('school', 1)).to(be, 'Concordia')
43
+ expect(SetBuilder.getValue('school', '1')).to(be, 'Concordia')
44
+ end
45
+
46
+ it 'should return what it was passed if there is no value map for the key'
47
+ expect(SetBuilder.getValue('band', 1)).to(be, 1)
48
+ end
49
+ end
50
+
51
+ describe '.getValueMaps'
52
+ it 'should return the names of the value maps registered'
53
+ expect(SetBuilder.getValueMaps()).to(eql, ['school']);
54
+ end
55
+ end
56
+
57
+
58
+
59
+ describe '.Trait'
60
+
61
+ describe '.constructor'
62
+ it 'should correctly parse simple parameters'
63
+ var trait = new SetBuilder.Trait(['awesome', 'reflexive']);
64
+ expect(trait.name()).to(be, 'awesome');
65
+ expect(trait.toString()).to(eql, 'who are awesome');
66
+ end
67
+
68
+ it 'should correctly identify direct objects'
69
+ var trait = new SetBuilder.Trait([['attended', 'string'], 'perfect']);
70
+ expect(trait.name()).to(be, 'attended');
71
+ expect(trait.requires_direct_object()).to(be, true);
72
+ expect(trait.toString()).to(eql, 'who have attended');
73
+ end
74
+
75
+ it 'should correctly parse paramters with modifiers'
76
+ var trait = new SetBuilder.Trait(['born', 'passive', ['date']]);
77
+ expect(trait.modifiers().length).to(be, 1);
78
+ expect(trait.toString()).to(eql, 'who were born');
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+
85
+
86
+ describe '.Traits'
87
+ before_each
88
+ traits = SetBuilder.traits();
89
+ end
90
+
91
+ describe '.length'
92
+ it 'should have parsed the data structure correctly'
93
+ expect(traits.length()).to(be, 5);
94
+ end
95
+ end
96
+
97
+ describe '.find'
98
+ it 'should get a SetBuilder.Trait object by name'
99
+ expect(traits.__find('awesome').toString()).to(eql, 'who are awesome');
100
+ expect(traits.__find('died').toString()).to(eql, 'who died');
101
+ expect(traits.__find('born').toString()).to(eql, 'who were born');
102
+ expect(traits.__find('attended').toString()).to(eql,'who have attended');
103
+ expect(traits.__find('name').toString()).to(eql, 'whose name');
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+
110
+
111
+ describe '.Modifiers'
112
+ before_each
113
+ modifiers = SetBuilder.modifiers();
114
+ end
115
+
116
+ describe '.length'
117
+ it 'should have parsed the data structure correctly'
118
+ expect(modifiers.length()).to(be, 1);
119
+ end
120
+ end
121
+
122
+ describe '.operators_for'
123
+ it 'should get the modifiers for the "string" modifier'
124
+ var expected_modifiers = ['contains', 'begins_with', 'ends_with', 'is'];
125
+ expect(modifiers.operators_for('string')).to(eql, expected_modifiers);
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ describe '.Set'
132
+
133
+ describe '.constraints'
134
+ it 'should have parsed the correct number of objects'
135
+ var set = new SetBuilder.Set(set_data);
136
+ expect(set.constraints().length).to(be, 4);
137
+ end
138
+ end
139
+
140
+ describe '.toString'
141
+ it 'should generate the natural language description of a simple set'
142
+ var simple_set = new SetBuilder.Set([['awesome']]);
143
+ expect(simple_set.toString()).to(eql, 'who are awesome');
144
+ end
145
+
146
+ it 'should generate the natural language description of a complex set'
147
+ var set = new SetBuilder.Set(set_data);
148
+ var expected_string = 'who are awesome, who have attended McKendree, who died, and whose name is Jerome'
149
+ expect(set.toString()).to(be, expected_string);
150
+ end
151
+
152
+ it 'should generate the natural language description of a complex set with negation (NB: nouns are not negated)'
153
+ var set = new SetBuilder.Set([
154
+ ['!awesome'],
155
+ ['!attended', 1],
156
+ ['!died'],
157
+ ['!name', {'is': "Jerome"}]
158
+ ]);
159
+ var expected_string = 'who are not awesome, who have not attended Concordia, who have not died, and whose name is Jerome'
160
+ expect(set.toString()).to(eql, expected_string);
161
+ end
162
+ end
163
+
164
+ end
165
+ end
166
+
File without changes
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ class DateModifierTest < ActiveSupport::TestCase
4
+ include SetBuilder::Modifiers
5
+
6
+
7
+ test "should constrain our date queries to A.D." do
8
+ modifier = DateModifier.new({:in_the_last => [Date.today.year, "years"]})
9
+ assert_equal "x>='0001-01-01'", modifier.build_conditions_for("x")
10
+ end
11
+
12
+
13
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class InflectorTest < ActiveSupport::TestCase
4
+
5
+
6
+ test "active" do
7
+ assert_equal "who died", SetBuilder::Trait.new("died", :active).to_s
8
+ end
9
+
10
+ test "perfect" do
11
+ assert_equal "who have attended", SetBuilder::Trait.new("attended", :perfect).to_s
12
+ end
13
+
14
+ test "passive" do
15
+ assert_equal "who were born", SetBuilder::Trait.new("born", :passive).to_s
16
+ end
17
+
18
+ test "reflexive" do
19
+ assert_equal "who are awesome", SetBuilder::Trait.new("awesome", :reflexive).to_s
20
+ end
21
+
22
+ test "noun" do
23
+ assert_equal "whose name", SetBuilder::Trait.new("name", :noun).to_s
24
+ end
25
+
26
+
27
+ end
@@ -0,0 +1,90 @@
1
+ require 'test_helper'
2
+
3
+ class ModifierTest < ActiveSupport::TestCase
4
+ include SetBuilder::Modifiers
5
+
6
+
7
+ test "get type with string" do
8
+ assert_equal StringModifier, SetBuilder::Modifier["String"]
9
+ end
10
+
11
+ test "get type with symbol" do
12
+ assert_equal StringModifier, SetBuilder::Modifier[:string]
13
+ end
14
+
15
+ test "registering a modifier" do
16
+ assert_raises ArgumentError do
17
+ SetBuilder::Modifier.for(:hash)
18
+ end
19
+ SetBuilder::Modifier.register(:hash, HashModifier)
20
+ assert_nothing_raised ArgumentError do
21
+ SetBuilder::Modifier.for(:hash)
22
+ end
23
+ end
24
+
25
+ test "registering an invalid modifier" do
26
+ assert_raises ArgumentError do
27
+ SetBuilder::Modifier.register(:hash, InvalidHashModifier)
28
+ end
29
+ end
30
+
31
+ test "converting modifier to json" do
32
+ expected_results = {
33
+ "contains" => ["string"],
34
+ "does_not_contain" => ["string"],
35
+ "begins_with" => ["string"],
36
+ "does_not_begin_with" => ["string"],
37
+ "ends_with" => ["string"],
38
+ "does_not_end_with" => ["string"],
39
+ "is" => ["string"],
40
+ "is_not" => ["string"]
41
+ }.to_json
42
+ assert_equal expected_results, SetBuilder::Modifier.for(:string).to_json
43
+ end
44
+
45
+ test "converting modifiers to json" do
46
+ expected_results = {
47
+ "date" => {
48
+ "ever" => [],
49
+ "after" => ["date"],
50
+ "before" => ["date"],
51
+ "on" => ["date"],
52
+ "in_the_last" => ["number", "period"],
53
+ "during_month"=> ["month"],
54
+ "during_year" => ["year"],
55
+ "between" => ["date", "date"]
56
+ },
57
+ "number"=> {
58
+ "is"=>["number"],
59
+ "is_less_than"=>["number"],
60
+ "is_greater_than"=>["number"],
61
+ "is_between"=>["number", "number"]
62
+ },
63
+ "string" => {
64
+ "contains" => ["string"],
65
+ "does_not_contain" => ["string"],
66
+ "begins_with" => ["string"],
67
+ "does_not_begin_with" => ["string"],
68
+ "ends_with" => ["string"],
69
+ "does_not_end_with" => ["string"],
70
+ "is" => ["string"],
71
+ "is_not" => ["string"]
72
+ }
73
+ }
74
+ assert_equal expected_results, Friend.modifiers.to_hash
75
+ end
76
+
77
+
78
+ end
79
+
80
+
81
+ class InvalidHashModifier
82
+ end
83
+
84
+ class HashModifier < SetBuilder::Modifier::Verb
85
+
86
+ def self.operators
87
+ [:has_key]
88
+ end
89
+
90
+ end
data/test/set_test.rb ADDED
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+
3
+ class SetTest < ActiveSupport::TestCase
4
+
5
+
6
+
7
+ test "FakeScope" do
8
+ assert_equal [5, 4, 3, 2], FakeScope.new(5).scoped(4).scoped(3).scoped(2).composed_scope
9
+ end
10
+
11
+ test "set data struture" do
12
+ data = [
13
+ [:awesome],
14
+ [:attended, 2],
15
+ [:died],
16
+ [:name, {:is => "Jerome"}]]
17
+ set = Friend.that_belong_to(data)
18
+ assert set.valid?
19
+ assert_equal "who are awesome, who have attended McKendree, who died, and whose name is Jerome", set.to_s
20
+ end
21
+
22
+ test "sets with invalid modifiers should be invalid" do
23
+ data = [[:born, {:after => ["wrong"]}]]
24
+ set = Friend.that_belong_to(data)
25
+ assert_equal false, set.valid?
26
+ end
27
+
28
+ test "sets should not allow non-numbers in a number modifiers" do
29
+ data = [[:age, {:is => ["12a"]}]]
30
+ set = Friend.that_belong_to(data)
31
+ refute set.valid?
32
+ end
33
+
34
+ test "sets should not allow empty string in a number modifiers" do
35
+ data = [[:age, {:is => [""]}]]
36
+ set = Friend.that_belong_to(data)
37
+ refute set.valid?
38
+ end
39
+
40
+ test "sets lacking expected modifiers should be invalid" do
41
+ data = [[:born, {:ever => []}]]
42
+ set = Friend.that_belong_to(data)
43
+ assert_equal true, set.valid?
44
+
45
+ data = [[:born]]
46
+ set = Friend.that_belong_to(data)
47
+ assert_equal false, set.valid?
48
+ end
49
+
50
+ test "set structure with negations (nouns are ignored)" do
51
+ data = [
52
+ ["!awesome"],
53
+ ["!attended", 2],
54
+ ["!died"],
55
+ ["!name", {:is => "Jerome"}]]
56
+ set = Friend.that_belong_to(data)
57
+ assert set.valid?
58
+ assert_equal "who are not awesome, who have not attended McKendree, who have not died, and whose name is Jerome", set.to_s
59
+ end
60
+
61
+ test "simple perform" do
62
+ data = [[:awesome]]
63
+ set = Friend.that_belong_to(data)
64
+
65
+ expected_results = [{:conditions => {:awesome => true}}]
66
+ # Friend.reset_composed_scope
67
+ assert_equal expected_results, set.perform.composed_scope
68
+ end
69
+
70
+ test "complex perform" do
71
+ data = [
72
+ [:awesome],
73
+ [:attended, 1],
74
+ [:died],
75
+ [:name, {:begins_with => "Jerome"}]]
76
+ set = Friend.that_belong_to(data)
77
+
78
+ expected_results = [
79
+ {:conditions => {:awesome => true}},
80
+ {:joins => "INNER JOIN schools ON friends.school_id=schools.id", :conditions => {"schools.id" => 1}},
81
+ {:conditions => {:alive => false}},
82
+ {:conditions => ["friends.name LIKE ?", "Jerome%"]}
83
+ ]
84
+ # Friend.reset_composed_scope
85
+ assert_equal expected_results, set.perform.composed_scope
86
+ end
87
+
88
+ test "invalid set" do
89
+ data = [[:name, {:starts_with => "Jerome"}]] # starts_with is not a valid operator
90
+ set = Friend.that_belong_to(data)
91
+
92
+ # !todo: what to do?
93
+ end
94
+
95
+
96
+ end