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.
- 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
|