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
@@ -0,0 +1,3 @@
1
+ require 'set_builder/modifiers/string_modifier'
2
+ require 'set_builder/modifiers/date_modifier'
3
+ require 'set_builder/modifiers/number_modifier'
@@ -0,0 +1,83 @@
1
+ require 'set_builder/modifier/adverb'
2
+
3
+
4
+ module SetBuilder
5
+ module Modifiers
6
+ class DateModifier < Modifier::Adverb
7
+
8
+
9
+
10
+ def self.operators
11
+ {
12
+ :ever => [],
13
+ :before => [:date],
14
+ :after => [:date],
15
+ :on => [:date],
16
+ :during_month => [:month],
17
+ :during_year => [:year],
18
+ :in_the_last => [:number, :period],
19
+ :between => [:date, :date]
20
+ }
21
+ end
22
+
23
+
24
+
25
+ def build_conditions_for(selector)
26
+ case operator
27
+ when :ever
28
+ "#{selector} IS NOT NULL"
29
+ when :before
30
+ "#{selector}<'#{format_value(get_date)}'"
31
+ when :after
32
+ "#{selector}>'#{format_value(get_date)}'"
33
+ when :on
34
+ "#{selector}='#{format_value(get_date)}'"
35
+ when :during_month
36
+ "extract(month from #{selector})=#{values[0].to_i}"
37
+ when :during_year
38
+ year = values[0].to_i
39
+ return "TRUE" if year <= 0
40
+ "#{selector} BETWEEN '#{year}-01-01' AND '#{year}-12-31'"
41
+ when :in_the_last
42
+ "#{selector}>='#{format_value(get_date)}'"
43
+ when :between
44
+ "#{selector} BETWEEN '#{format_value(Date.parse values[0])}' AND '#{format_value(Date.parse values[1])}'"
45
+ end
46
+ end
47
+
48
+
49
+
50
+ protected
51
+
52
+
53
+
54
+ def get_date
55
+ case operator
56
+ when :in_the_last
57
+ case values[1]
58
+ when "years", "year"
59
+ values[0].to_i.years.ago
60
+ when "months", "month"
61
+ values[0].to_i.months.ago
62
+ when "weeks", "week"
63
+ values[0].to_i.weeks.ago
64
+ when "days", "day"
65
+ values[0].to_i.days.ago
66
+ end
67
+ else
68
+ Date.parse values[0]
69
+ end
70
+ end
71
+
72
+
73
+
74
+ def format_value(date)
75
+ date = [Date.new(1,1,1), date].max # constrain dates to A.D.
76
+ date.strftime('%Y-%m-%d')
77
+ end
78
+
79
+
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,48 @@
1
+ require 'set_builder/modifier/verb'
2
+
3
+
4
+ module SetBuilder
5
+ module Modifiers
6
+ class NumberModifier < Modifier::Verb
7
+
8
+
9
+
10
+ def self.operators
11
+ {
12
+ :is => [:number],
13
+ :is_less_than => [:number],
14
+ :is_greater_than => [:number],
15
+ :is_between => [:number, :number]
16
+ }
17
+ end
18
+
19
+
20
+
21
+ def build_conditions_for(selector)
22
+ case operator
23
+ when :is
24
+ ["#{selector}=?", format_value]
25
+ when :is_less_than
26
+ ["#{selector}<?", format_value]
27
+ when :is_greater_than
28
+ ["#{selector}>?", format_value]
29
+ when :is_between
30
+ ["#{selector}>=? AND #{selector}<=?", values[0], values[1]]
31
+ end
32
+ end
33
+
34
+
35
+
36
+ private
37
+
38
+
39
+
40
+ def format_value
41
+ values[0]
42
+ end
43
+
44
+
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,81 @@
1
+ require 'set_builder/modifier/verb'
2
+
3
+
4
+ module SetBuilder
5
+ module Modifiers
6
+ class StringModifier < Modifier::Verb
7
+
8
+
9
+
10
+ def self.operators
11
+ {
12
+ :contains => [:string],
13
+ :does_not_contain => [:string],
14
+ :begins_with => [:string],
15
+ :does_not_begin_with => [:string],
16
+ :ends_with => [:string],
17
+ :does_not_end_with => [:string],
18
+ :is => [:string],
19
+ :is_not => [:string]
20
+ }
21
+ end
22
+
23
+
24
+
25
+ def self.negate(operator)
26
+ case operator
27
+ when :contains
28
+ "does not contain"
29
+ when :begins_with
30
+ "does not begin with"
31
+ when :ends_with
32
+ "does not end with"
33
+ when :is
34
+ "is not"
35
+ end
36
+ end
37
+
38
+
39
+
40
+ def build_conditions_for(selector, operator=nil)
41
+ operator ||= self.operator
42
+ case operator
43
+
44
+ when :does_not_contain
45
+ negate(selector, :contains)
46
+ when :does_not_begin_with
47
+ negate(selector, :begins_with)
48
+ when :does_not_end_with
49
+ negate(selector, :ends_with)
50
+ when :is_not
51
+ negate(selector, :is)
52
+
53
+ when :is
54
+ ["#{selector}=?", values[0]]
55
+ else
56
+ ["#{selector} LIKE ?", get_like_value_for_operator]
57
+ end
58
+ end
59
+
60
+
61
+
62
+ private
63
+
64
+
65
+
66
+ def get_like_value_for_operator
67
+ case operator
68
+ when :contains
69
+ "%#{values[0]}%"
70
+ when :begins_with
71
+ "#{values[0]}%"
72
+ when :ends_with
73
+ "%#{values[0]}"
74
+ end
75
+ end
76
+
77
+
78
+
79
+ end
80
+ end
81
+ end
File without changes
@@ -0,0 +1,81 @@
1
+ module SetBuilder
2
+ class Set
3
+
4
+
5
+
6
+ def initialize(model_or_scope, raw_data)
7
+ @model, @scope = get_model_and_scope(model_or_scope)
8
+ @set = raw_data
9
+ end
10
+
11
+
12
+
13
+ attr_reader :model
14
+
15
+
16
+
17
+ def constraints
18
+ @constraints ||= get_constraints
19
+ end
20
+
21
+
22
+
23
+ #
24
+ # Returns true if all of the constraints in this set are valid
25
+ #
26
+ def valid?
27
+ constraints.all?(&:valid?)
28
+ end
29
+
30
+
31
+
32
+ #
33
+ # Describes this set in natural language
34
+ #
35
+ def to_s
36
+ constraints.to_sentence
37
+ end
38
+
39
+
40
+
41
+ #
42
+ # Returns an instance of ActiveRecord::NamedScope::Scope
43
+ # which can fetch the objects which belong to this set
44
+ #
45
+ def perform
46
+ constraints.inject(@scope) {|scope, constraint| constraint.perform(scope)}
47
+ end
48
+
49
+
50
+
51
+ private
52
+
53
+
54
+
55
+ def get_constraints
56
+ @set.inject([]) do |constraints, line|
57
+ negate, trait_name, args = false, line.first.to_s, line[1..-1]
58
+ trait_name, negate = trait_name[1..-1], true if (trait_name[0..0] == "!")
59
+ trait = model.traits[trait_name]
60
+ raise("\"#{trait_name}\" is not a trait for #{model}") unless trait
61
+ constraints << trait.apply(*args).negate(negate)
62
+ end
63
+ end
64
+
65
+
66
+
67
+ # !todo: this can be overriden or factored out to allow SetBuilder
68
+ # to be used with other ORMs like DataMapper
69
+ def get_model_and_scope(model_or_scope)
70
+ if defined?(ActiveRecord::NamedScope::Scope) && model_or_scope.is_a?(ActiveRecord::NamedScope::Scope)
71
+ [model_or_scope.proxy_scope, model_or_scope]
72
+ else
73
+ # [model_or_scope, model_or_scope.scoped({})]
74
+ [model_or_scope, model_or_scope.scoped]
75
+ end
76
+ end
77
+
78
+
79
+
80
+ end
81
+ end
@@ -0,0 +1,74 @@
1
+ require 'set_builder/constraint'
2
+ require 'set_builder/modifier'
3
+
4
+
5
+ module SetBuilder
6
+ class Trait
7
+
8
+
9
+
10
+ def initialize(name, part_of_speech, *args, &block)
11
+ case name
12
+ when Hash
13
+ @name, @direct_object_type = name.first[0].to_s, name.first[1]
14
+ else
15
+ @name = name.to_s
16
+ end
17
+ @part_of_speech, @block = part_of_speech, block
18
+ @modifiers = (args||[]).collect {|modifier| Modifier[modifier]}
19
+ end
20
+
21
+
22
+
23
+ attr_reader :name, :part_of_speech, :modifiers, :direct_object_type
24
+
25
+
26
+
27
+ def requires_direct_object?
28
+ !@direct_object_type.nil?
29
+ end
30
+ alias :direct_object_required? :requires_direct_object?
31
+
32
+
33
+
34
+ def noun?
35
+ (self.part_of_speech == :noun)
36
+ end
37
+
38
+
39
+
40
+ def to_s(negative=false)
41
+ case part_of_speech
42
+ when :active
43
+ negative ? "who have not #{name}" : "who #{name}"
44
+ when :perfect
45
+ negative ? "who have not #{name}" : "who have #{name}"
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
53
+ end
54
+
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
63
+ end
64
+
65
+
66
+
67
+ def apply(*args)
68
+ SetBuilder::Constraint.new(self, *args, &@block)
69
+ end
70
+
71
+
72
+
73
+ end
74
+ end
@@ -0,0 +1,42 @@
1
+ require 'set_builder/trait'
2
+ require 'set_builder/modifier_collection'
3
+
4
+
5
+ module SetBuilder
6
+ class Traits < Array
7
+
8
+
9
+
10
+ def [](index)
11
+ case index
12
+ when Symbol, String
13
+ index = index.to_s
14
+ self.find {|trait| trait.name == index}
15
+ else
16
+ super
17
+ end
18
+ end
19
+
20
+
21
+
22
+ def to_json
23
+ "[#{collect(&:to_json).join(",")}]"
24
+ end
25
+
26
+
27
+
28
+ def modifiers
29
+ # !nb: not sure why inject was failing but it was modifying trait.modifiers!
30
+ @modifiers = ModifierCollection.new
31
+ each do |trait|
32
+ trait.modifiers.each do |modifier|
33
+ @modifiers << modifier unless @modifiers.member?(modifier)
34
+ end
35
+ end
36
+ @modifiers
37
+ end
38
+
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ module SetBuilder
2
+ module ValueMap
3
+
4
+
5
+
6
+ @registered_value_maps = {}
7
+
8
+
9
+
10
+ def self.registered?(name)
11
+ name = name.to_sym
12
+ @registered_value_maps.key?(name)
13
+ end
14
+
15
+
16
+
17
+ def self.to_s(name, value)
18
+ name = name.to_sym
19
+ map = @registered_value_maps[name]
20
+ if map
21
+ pair = map.find {|pair| pair[0] == value}
22
+ pair ? pair[1].to_s : "(unknown)"
23
+ else
24
+ value.to_s
25
+ end
26
+ end
27
+
28
+
29
+
30
+ def self.for(name)
31
+ name = name.to_sym
32
+ @registered_value_maps[name] || raise(ArgumentError, "A value map has not been registered for #{value}")
33
+ end
34
+
35
+
36
+
37
+ def self.register_collection(name, collection, name_method = :name, id_method = :id)
38
+ map = collection.map {|i| [i.send(id_method).to_s, i.send(name_method)]}
39
+ register(name, map)
40
+ end
41
+
42
+
43
+
44
+ def self.register(name, map)
45
+ raise "map is expected to be an array of pairs" unless map.is_a?(Array)
46
+ name = name.to_sym
47
+ @registered_value_maps[name] = map
48
+ end
49
+
50
+
51
+
52
+ def self.to_json
53
+ @registered_value_maps.to_json
54
+ end
55
+
56
+
57
+
58
+ end
59
+
60
+
61
+
62
+ end