set_builder 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +35 -0
- data/Rakefile +14 -0
- data/assets/javascripts/array.js +100 -0
- data/assets/javascripts/set_builder.js +415 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/set_builder.rb +58 -0
- data/lib/set_builder/constraint.rb +67 -0
- data/lib/set_builder/modifier.rb +134 -0
- data/lib/set_builder/modifier/adverb.rb +11 -0
- data/lib/set_builder/modifier/base.rb +105 -0
- data/lib/set_builder/modifier/verb.rb +24 -0
- data/lib/set_builder/modifier_collection.rb +41 -0
- data/lib/set_builder/modifiers.rb +3 -0
- data/lib/set_builder/modifiers/date_modifier.rb +83 -0
- data/lib/set_builder/modifiers/number_modifier.rb +48 -0
- data/lib/set_builder/modifiers/string_modifier.rb +81 -0
- data/lib/set_builder/query_builders/string.rb +0 -0
- data/lib/set_builder/set.rb +81 -0
- data/lib/set_builder/trait.rb +74 -0
- data/lib/set_builder/traits.rb +42 -0
- data/lib/set_builder/value_map.rb +62 -0
- data/lib/set_builder/version.rb +3 -0
- data/set_builder.gemspec +25 -0
- data/spec/commands/example_command.rb +19 -0
- data/spec/dom.html +24 -0
- data/spec/lib/images/bg.png +0 -0
- data/spec/lib/images/hr.png +0 -0
- data/spec/lib/images/loading.gif +0 -0
- data/spec/lib/images/sprites.bg.png +0 -0
- data/spec/lib/images/sprites.png +0 -0
- data/spec/lib/images/vr.png +0 -0
- data/spec/lib/jspec.css +149 -0
- data/spec/lib/jspec.growl.js +115 -0
- data/spec/lib/jspec.jquery.js +88 -0
- data/spec/lib/jspec.js +1908 -0
- data/spec/lib/jspec.nodejs.js +18 -0
- data/spec/lib/jspec.shell.js +39 -0
- data/spec/lib/jspec.timers.js +154 -0
- data/spec/lib/jspec.xhr.js +210 -0
- data/spec/node.js +10 -0
- data/spec/rhino.js +10 -0
- data/spec/server.html +18 -0
- data/spec/server.rb +4 -0
- data/spec/unit/array.spec.js +82 -0
- data/spec/unit/set_builder.spec.js +166 -0
- data/spec/unit/spec.helper.js +0 -0
- data/test/date_modifier_test.rb +13 -0
- data/test/inflector_test.rb +27 -0
- data/test/modifier_test.rb +90 -0
- data/test/set_test.rb +96 -0
- data/test/test_helper.rb +79 -0
- data/test/trait_test.rb +49 -0
- data/test/traits_test.rb +41 -0
- data/test/value_map_test.rb +30 -0
- data/uninstall.rb +1 -0
- metadata +191 -0
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'set_builder'
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/lib/set_builder.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'set_builder/traits'
|
4
|
+
require 'set_builder/modifiers'
|
5
|
+
require 'set_builder/value_map'
|
6
|
+
require 'set_builder/set'
|
7
|
+
|
8
|
+
|
9
|
+
module SetBuilder
|
10
|
+
|
11
|
+
|
12
|
+
def self.extended(base)
|
13
|
+
base.instance_variable_set("@traits", SetBuilder::Traits.new)
|
14
|
+
base.send(:include, SetBuilder::Modifiers)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
attr_reader :traits
|
19
|
+
|
20
|
+
|
21
|
+
def modifiers
|
22
|
+
traits.modifiers
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def that_belong_to(set)
|
27
|
+
SetBuilder::Set.new(self, set)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
def trait(*args, &block)
|
36
|
+
part_of_speech = get_part_of_speech(args.shift)
|
37
|
+
name = args.shift
|
38
|
+
traits << Trait.new(name, part_of_speech, *args, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def get_part_of_speech(arg)
|
43
|
+
case arg
|
44
|
+
when :is, :are, :reflexive
|
45
|
+
:reflexive
|
46
|
+
when nil, :active
|
47
|
+
:active
|
48
|
+
when :was, :were, :passive
|
49
|
+
:passive
|
50
|
+
when :has, :have, :perfect
|
51
|
+
:perfect
|
52
|
+
when :whose, :noun
|
53
|
+
:noun
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'set_builder/modifier'
|
2
|
+
|
3
|
+
|
4
|
+
module SetBuilder
|
5
|
+
class Constraint
|
6
|
+
|
7
|
+
|
8
|
+
#
|
9
|
+
# Sample constraints:
|
10
|
+
#
|
11
|
+
# [:awesome],
|
12
|
+
# [:attended, "school"],
|
13
|
+
# [:died],
|
14
|
+
# [:name, {:is => "Jerome"}]]
|
15
|
+
#
|
16
|
+
def initialize(trait, *args, &block)
|
17
|
+
@trait, @block = trait, block
|
18
|
+
@direct_object = args.shift if trait.requires_direct_object?
|
19
|
+
@modifiers = trait.modifiers.collect {|modifier_type| modifier_type.new(args.shift)}
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
attr_reader :trait, :direct_object, :modifiers, :negative
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
delegate :direct_object_required?,
|
29
|
+
:direct_object_type,
|
30
|
+
:to => :trait
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
(!direct_object_required? or !direct_object.nil?) and modifiers.all?(&:valid?)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
# p "ValueMap.to_s(#{direct_object_type} (#{direct_object_type.class}), #{direct_object} (#{direct_object.class}))"
|
42
|
+
@description ||= begin
|
43
|
+
description = trait.to_s(@negative)
|
44
|
+
description << " #{ValueMap.to_s(direct_object_type, direct_object)}" if direct_object_required?
|
45
|
+
description << " #{modifiers.collect{|m| m.to_s(@negative)}.join(" ")}" unless modifiers.empty?
|
46
|
+
description
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
def negate(value)
|
53
|
+
@negative = value
|
54
|
+
@negative = false if trait.noun?
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def perform(scope)
|
61
|
+
scope.scoped(@block.call(self, scope))
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'set_builder/modifiers'
|
2
|
+
require 'set_builder/modifier/adverb'
|
3
|
+
require 'set_builder/modifier/verb'
|
4
|
+
|
5
|
+
module SetBuilder
|
6
|
+
module Modifier
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
@registered_modifiers = {}
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
def self.registered?(klass)
|
15
|
+
@registered_modifiers.values.member?(klass)
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
def self.name(klass)
|
21
|
+
@registered_modifiers.each do |key, value|
|
22
|
+
return key if (value == klass)
|
23
|
+
end
|
24
|
+
klass.name
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
def self.for(type)
|
30
|
+
type = get_type(type)
|
31
|
+
@registered_modifiers[type] || raise(ArgumentError, "A modifier has not been registered for #{type}")
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
def self.[](klass_or_symbol)
|
37
|
+
klass_or_symbol.is_a?(Class) ? SetBuilder::Modifier.valid_modifier!(klass_or_symbol) : SetBuilder::Modifier.for(klass_or_symbol)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
# Usage
|
44
|
+
# register(type, modifier)
|
45
|
+
# register([type, modifier], [type, modifier])
|
46
|
+
# register(type, modifier, type, modifier)
|
47
|
+
#
|
48
|
+
def self.register(*args)
|
49
|
+
args, i = args.flatten, 0
|
50
|
+
while args[i+1]
|
51
|
+
type, modifier_klass = get_type(args[i]), args[i+1]
|
52
|
+
valid_modifier!(modifier_klass) # || raise(ArgumentError, "#{modifier_klass} is not a valid modifier")
|
53
|
+
@registered_modifiers[type] = modifier_klass
|
54
|
+
i += 2
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def self.valid_modifier!(klass)
|
61
|
+
raise(ArgumentError, "#{klass} must inherit from either `SetBuilder::Modifier::Verb` or `SetBuilder::Modifier::Adverb`") unless (is_subclass_of?(klass, SetBuilder::Modifier::Adverb) or is_subclass_of?(klass, SetBuilder::Modifier::Verb))
|
62
|
+
raise(ArgumentError, "#{klass} must respond to `operators`") unless klass.respond_to?(:operators)
|
63
|
+
raise(ArgumentError, "#{klass}.operators must not be empty") if klass.operators.empty?
|
64
|
+
klass
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
def self.get_type(type)
|
74
|
+
if type.is_a?(Symbol)
|
75
|
+
type
|
76
|
+
else
|
77
|
+
type.to_s.downcase.to_sym
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
def self.is_subclass_of?(klass, superklass)
|
84
|
+
sc = klass
|
85
|
+
while (sc = sc.superclass)
|
86
|
+
return true if (sc == superklass)
|
87
|
+
end
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
#
|
98
|
+
# Force predefined modifiers to pass `valid_modifier?`
|
99
|
+
#
|
100
|
+
Modifier.register(
|
101
|
+
[:date, Modifiers::DateModifier],
|
102
|
+
[:number, Modifiers::NumberModifier],
|
103
|
+
[:string, Modifiers::StringModifier]
|
104
|
+
)
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
#
|
117
|
+
# Why is the below not working?
|
118
|
+
#
|
119
|
+
|
120
|
+
# class Class
|
121
|
+
#
|
122
|
+
#
|
123
|
+
#
|
124
|
+
# def is_subclass_of?(klass)
|
125
|
+
# sc = self
|
126
|
+
# while (sc = sc.superclass)
|
127
|
+
# return true if (sc == klass)
|
128
|
+
# end
|
129
|
+
# false
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
#
|
133
|
+
#
|
134
|
+
# end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module SetBuilder
|
2
|
+
module Modifier
|
3
|
+
class Base
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
def initialize(hash)
|
8
|
+
@operator, @values = (hash.is_a?(Hash) ? [hash.first[0].to_sym, hash.first[1]] : [nil, nil])
|
9
|
+
@values ||= []
|
10
|
+
@values = [@values] unless @values.is_a?(Array)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
attr_reader :operator, :values
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
valid_operator?(self.operator) && valid_arguments?(self.values)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
def valid_operator?(operator)
|
26
|
+
!operator.nil? && self.class.operators.key?(operator)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
def valid_arguments?(values)
|
32
|
+
argument_types = self.class.operators[operator] || []
|
33
|
+
return false unless (values.length == argument_types.length)
|
34
|
+
values.each_with_index do |value, i|
|
35
|
+
return false unless valid_argument_of_type?(value, argument_types[i])
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
def valid_argument_of_type?(argument, type)
|
43
|
+
validator = "valid_#{type}_argument?"
|
44
|
+
if respond_to?(validator)
|
45
|
+
send(validator, argument)
|
46
|
+
else
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
def valid_date_argument?(string)
|
54
|
+
begin
|
55
|
+
Date.parse(string)
|
56
|
+
true
|
57
|
+
rescue
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def valid_number_argument?(number)
|
64
|
+
!(number.to_s =~ /\A\d+\Z/).nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
def to_s(negative=false)
|
70
|
+
words = negative ? [self.class.negate(operator).to_s.gsub(/_/, " ")] : [operator.to_s.gsub(/_/, " ")]
|
71
|
+
arguments = self.class.operators[operator] || []
|
72
|
+
(0...arguments.length).each do |i|
|
73
|
+
# p "ValueMap.to_s(#{arguments[i]} (#{arguments[i].class}), #{values[i]} (#{values[i].class})): #{ValueMap.to_s(arguments[i], values[i])}"
|
74
|
+
words << ValueMap.to_s(arguments[i], values[i])
|
75
|
+
end
|
76
|
+
words.join(" ")
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
def self.negate(operator)
|
82
|
+
operator
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
def self.to_hash
|
88
|
+
hash = {}
|
89
|
+
operators.each do |operator, array|
|
90
|
+
hash[operator.to_s] = array.map {|type| type.to_s }
|
91
|
+
end
|
92
|
+
hash
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
def self.to_json
|
98
|
+
to_hash.to_json
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'set_builder/modifier/base'
|
2
|
+
|
3
|
+
|
4
|
+
module SetBuilder
|
5
|
+
module Modifier
|
6
|
+
class Verb < Base
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
def negate(selector, operator)
|
15
|
+
conditions = build_conditions_for(selector, operator)
|
16
|
+
conditions[0] = "NOT(#{conditions[0]})"
|
17
|
+
conditions
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SetBuilder
|
2
|
+
class ModifierCollection < Array
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
# def [](index)
|
7
|
+
# case index
|
8
|
+
# when Symbol, String
|
9
|
+
# index = index.to_s
|
10
|
+
# self.find {|trait| trait.name == index}
|
11
|
+
# else
|
12
|
+
# super
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
def to_hash
|
19
|
+
hash = {}
|
20
|
+
each do |modifier|
|
21
|
+
hash[Modifier.name(modifier).to_s] = modifier.to_hash
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
def to_json
|
29
|
+
to_hash.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
# def modifiers
|
35
|
+
# inject([]) {|modifiers, trait| modifiers.concat(trait.modifiers)}.uniq
|
36
|
+
# end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|