msfl 1.1.6 → 1.2.0.dev

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9034a3e616954189429dc66d76be624f065b5f9b
4
- data.tar.gz: 8ef828b22da3158dc126e3d8ae8a148bdf82f9b9
3
+ metadata.gz: 836568a1640ce165512978aa087ea16d8c87088e
4
+ data.tar.gz: d5898063d32d174b84522ab16a56265b4453b9a8
5
5
  SHA512:
6
- metadata.gz: fe03bb90fc8cd612c5914217600a02dfb3a8fd4a5e08e6f701b5e80cdb704f8128e8335c245300d7a2ed6ad2d45b051ac804b496b7386f7350f3484aecf0975d
7
- data.tar.gz: 920a0e38dbf3256d45695c60dced75252ddff4d8cf7babaa63825da13b72fb36c220dc13f08ccf364474b0478eb888c7854d01479b39c5e5562865b71ec24fc5
6
+ metadata.gz: 5df4af19fc17ababf06c3570af87f93021d6ff4dc7bfedf936dfe9942f3e4016d15e6eb5a8b4f73bb38292996ff173b36263eff1d0e24fe78a1f376f5662fcb2
7
+ data.tar.gz: ded9b1ceae6f7806502a2f8a3e0c5c3e5c19968c3a5dec9fac35e3d0f1ff7fe9eab8857feb13ae1ce92764ad085335a1ee16987861a60b2dc4a1172e5330eee6
data/README.md CHANGED
@@ -1,5 +1,18 @@
1
1
  [![Circle CI](https://circleci.com/gh/Referly/msfl.svg?style=svg)](https://circleci.com/gh/Referly/msfl)
2
2
 
3
+ # MSFL
4
+
5
+ The Mattermark Semantic Filter Language is a language for _filtering_ data. It allows users to construct filters
6
+ on sets of data in a Venn diagram like fashion. More formally it allows the user to create subsets of data.
7
+
8
+ MSFL is different than other languages - it is _not_ a query language. It has no notion of concepts like _order_,
9
+ _limit_, _offset_, _group_by_, or _having_.
10
+
11
+ It does support faceted filtering through a vocabulary added in 1.2 which allows the user to define filters
12
+ on the hyperset of the data. (In the non-hyper case all of the extra dimensions are simplified to constants.) If
13
+ you don't know what faceted filtering is or this sounds overwhelming, just ignore this bit. When you get to the point
14
+ that you need faceted filtering in your application then this will seem second nature.
15
+
3
16
  # Ruby Gem for the Mattermark Semantic Filter Language
4
17
 
5
18
  Contains serializers and validators (and perhaps other) MSFL goodies
@@ -8,27 +21,191 @@ Contains serializers and validators (and perhaps other) MSFL goodies
8
21
 
9
22
  MSFL is a context-free language. The context-free grammar is defined below.
10
23
 
11
- I'm not actually sure this is correct, it is definitely not comprehensive as it skips over the shortcut functionality.
24
+ # EXPRESSIONS
25
+
26
+ filter = lc , { filter_expr } , rc ;
27
+
28
+ filter_expr = range_expr
29
+ | binary_expr
30
+ | set_expr
31
+ | partial_expr
32
+ | foreign_expr ;
33
+
34
+ range_expr = between ;
35
+
36
+ binary_expr = comparisons
37
+ | containment ;
38
+
39
+ set_expr = and
40
+ | or ;
41
+
42
+ partial_expr = partial_op , colon , partial ;
43
+
44
+ foreign_expr = word , colon , filter ;
45
+
46
+ partial = lc , given_expr , comma , partial_filter , rc ;
47
+
48
+ given_expr = given_op , colon, filter ;
49
+
50
+ partial_filter = filter_op , colon , filter ;
51
+
52
+ between = value , colon , start_end
53
+ | value , colon , between_body ;
54
+
55
+ comparisons = comparison , { comma , comparison } ;
56
+
57
+ containment = word , colon , in_expr ;
58
+
59
+ and = and_op , colon , filters ;
60
+
61
+ or = or_op , colon , filters ;
62
+
63
+ comparison = word , colon , value
64
+ | word , colon , lc , comparison_list , rc ;
65
+
66
+ comparison_list = comparison_expr , { comma , comparison_expr } ;
67
+
68
+ comparison_expr = comparison_op , colon , value ;
69
+
70
+ in_expr = lc , in_op , colon , values , rc ;
71
+
72
+ filters = ls , { filter } , rs ;
73
+
74
+ values = ls , { value } , rs ;
75
+
76
+ between_body = lc , between_op , colon , start_end , rc ;
77
+
78
+ start_end = lc , start_expr , comma , end_expr , rc ;
79
+
80
+ start_expr = start_op , colon , range_value ;
81
+
82
+ end_expr = end_op , colon , range_value ;
83
+
84
+
85
+
86
+ # OPERATORS
87
+
88
+ partial_op = dq , "partial" , dq ;
89
+
90
+ given_op = dq , "given" , dq ;
91
+
92
+ filter_op = dq , "filter" , dq ;
93
+
94
+ in_op = dq , "in" , dq ;
95
+
96
+ between_op = dq , "between" , dq ;
97
+
98
+ start_op = dq , "start" , dq ;
99
+
100
+ end_op = dq , "end" , dq ;
101
+
102
+ comparison_op = lt_op
103
+ | gt_op
104
+ | lte_op
105
+ | gte_op
106
+ | eq_op ;
107
+
108
+ lt_op = dq , "lt" , dq ;
109
+
110
+ gt_op = dq , "gt" , dq ;
111
+
112
+ lte_op = dq , "lte" , dq ;
113
+
114
+ gte_op = dq , "gte" , dq ;
115
+
116
+ eq_op = dq , "eq" , dq ;
117
+
118
+ and_op = dq , "and" , dq ;
119
+
120
+ or_op = dq , "or" , dq ;
121
+
122
+
123
+
124
+ # VALUES AND TYPES
125
+
126
+ range_value = number
127
+ | date
128
+ | datetime
129
+ | time ;
130
+
131
+ value = word
132
+ | range_value
133
+ | boolean ;
134
+
135
+ word = dq , character , { character } , dq ;
136
+
137
+ number = integer | decimal ;
138
+
139
+ integer = [ hyphen ] , digit , { digit } ;
140
+
141
+ decimal = integer
142
+ | { integer } , dot , { digit } ;
143
+
144
+ boolean = true | false ;
145
+
146
+ true = "true"
147
+ | dq , "true" , dq
148
+ | "1"
149
+ | dq , "1" , dq ;
150
+
151
+ false = "false"
152
+ | dq , "false" , dq
153
+ | "0"
154
+ | dq , "0" , dq ;
155
+
156
+ date = ? ISO 8601 date format http://en.wikipedia.org/wiki/ISO_8601 ? ;
157
+
158
+ datetime = ? ISO 8601 combined date and time format http://en.wikipedia.org/wiki/ISO_8601 ? ;
159
+
160
+ time = ? ISO 8601 time format http://en.wikipedia.org/wiki/ISO_8601 ? ;
161
+
162
+ character = letter
163
+ | digit
164
+ | symbol ;
165
+
166
+ letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
167
+ | "H" | "I" | "J" | "K" | "L" | "M" | "N"
168
+ | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
169
+ | "V" | "W" | "X" | "Y" | "Z"
170
+ | "a" | "b" | "c" | "d" | "e" | "f" | "g"
171
+ | "h" | "i" | "j" | "k" | "l" | "m" | "n"
172
+ | "o" | "p" | "q" | "r" | "s" | "t" | "u"
173
+ | "v" | "w" | "x" | "y" | "z" ;
174
+
175
+ digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
176
+
177
+ symbol = "'" | "~" | "." | "_" | "-" | ":" | "?" | "/" | "=" | "@" | "&" ;
178
+
179
+ left_curly = "{" ;
180
+
181
+ lc = left_curly ;
182
+
183
+ right_curly = "}" ;
184
+
185
+ rc = right_curly ;
186
+
187
+ left_square = "[" ;
188
+
189
+ ls = left_square ;
190
+
191
+ right_square = "]" ;
192
+
193
+ rs = right_square ;
194
+
195
+ comma = "," ;
196
+
197
+ hyphen = "-" ;
198
+
199
+ colon = ":" ;
200
+
201
+ double_quote = '"' ;
202
+
203
+ dq = double_quote ;
204
+
205
+ dot = "." ;
206
+
207
+
12
208
 
13
- ```
14
- filter = range_op | binary_op | set_op
15
- set_op = and | or
16
- and = "{" "\"and\"" ":" list "}"
17
- or = "{" "\"or\"" ":" list "}"
18
- list = "[" filter? | (filter ("," filter)*) "]";
19
- range_op = between;
20
- between = "{" field ":" between_body | "{" "\"between\"" ":" between_body "}";
21
- between_body = "{" "\"start\"" ":" between_start "," "\"end\"" ":" between_end "}";
22
- between_start = integer | double | date | datetime | time;
23
- between_end = integer | double | date | datetime | time;
24
- binary_op = comparison | containment;
25
- comparison = "{" field ":" "{" comparison_op ":" atom "}" "}";
26
- field = "\"" ALPHANUMERIC+ "\"";
27
- comparison_op = "lt" | "gt" | "lte" | "gte" | "eq";
28
- containment = "{" field ":" "{" "\"in\"" ":" atom_list "}" "}";
29
- atom = string | integer | double | boolean | date | datetime | time;
30
- atom_list = "[" atom? | (atom ("," atom)*) "]";
31
- ```
32
209
 
33
210
  ## Configuration
34
211
 
@@ -69,6 +246,14 @@ After parsing a MSFL filter it can be validated. Currently the validation is pri
69
246
  semantic validation on a per dataset basis. This will allow per attribute validations to be setup by the consumer
70
247
  of this gem, which will be run automatically during validation.
71
248
 
249
+ Validation works in the following order
250
+
251
+ 1. Grammar validation
252
+
253
+ 2. Dataset configured validation
254
+
255
+ 3. Dataset semantic validation
256
+
72
257
  ## Frameworks
73
258
 
74
259
  ### Sinatra
@@ -8,7 +8,7 @@ module MSFL
8
8
  register_dataset
9
9
 
10
10
  def fields
11
- [:make, :model, :year, :value]
11
+ [:make, :model, :year, :value, :owner]
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,15 @@
1
+ require_relative 'base'
2
+
3
+ module MSFL
4
+ module Datasets
5
+ # This is a fake dataset definition that shows the structure for composing your own and is used for testing
6
+ # msfl
7
+ class Person < ::MSFL::Datasets::Base
8
+ register_dataset
9
+
10
+ def fields
11
+ [:name, :gender, :age, :cars]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -16,7 +16,7 @@ module MSFL
16
16
  obj
17
17
  end
18
18
 
19
- # Converts Ruby Arrays is a partially parsed Ruby MSFL filter to MSFL::Types::Set objects
19
+ # Converts Ruby Arrays in a partially parsed Ruby MSFL filter to MSFL::Types::Set objects
20
20
  #
21
21
  # @param obj [Object] the object in which to convert Ruby Array objects to MSFL::Types::Set objects
22
22
  # @return [Object] the result of converting Ruby Arrays to MSFL::Types::Set objects
data/msfl.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'msfl'
3
- s.version = '1.1.6'
4
- s.date = '2015-04-01'
3
+ s.version = '1.2.0.dev'
4
+ s.date = '2015-05-12'
5
5
  s.summary = "MSFL in Ruby"
6
6
  s.description = "Serializers, validators, and other tasty goodness for the Mattermark Semantic Filter Language in Ruby."
7
7
  s.authors = ["Courtland Caldwell"]
@@ -34,6 +34,27 @@ describe "MSFL::Parsers::JSON" do
34
34
  it { is_expected.to be_a MSFL::Types::Set }
35
35
  end
36
36
 
37
+ context "when parsing a foreign" do
38
+
39
+ # The test scenario here is if we are limiting the set of cars by person criteria (only cars owned by people over 25)
40
+
41
+ let(:test_json) { '{"person":{"age":{"gte":25}}}' }
42
+
43
+ it "is an equivalent Ruby hash" do
44
+ expect(mut).to eq({ person: { age: { gte: 25 } } })
45
+ end
46
+
47
+ end
48
+
49
+ context "when parsing a partial" do
50
+
51
+ let(:test_json) { '{"partial":{"given":{"make":"Toyota"},"filter":{"avg_age":10}}}'}
52
+
53
+ it "is an equivalent Ruby Hash" do
54
+ expect(mut).to eq({ partial: { given: { make: "Toyota" }, filter: { avg_age: 10 } } })
55
+ end
56
+ end
57
+
37
58
  end
38
59
 
39
60
  describe ".arrays_to_sets" do
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.2.0.dev
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-01 00:00:00.000000000 Z
11
+ date: 2015-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0.9'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.9'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0.8'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.8'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '3.1'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.1'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: byebug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '3.5'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.5'
97
97
  description: Serializers, validators, and other tasty goodness for the Mattermark
@@ -101,7 +101,7 @@ executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
- - .gitignore
104
+ - ".gitignore"
105
105
  - Gemfile
106
106
  - Gemfile.lock
107
107
  - LICENSE
@@ -116,6 +116,7 @@ files:
116
116
  - lib/msfl/datasets/base.rb
117
117
  - lib/msfl/datasets/car.rb
118
118
  - lib/msfl/datasets/movie.rb
119
+ - lib/msfl/datasets/person.rb
119
120
  - lib/msfl/parsers.rb
120
121
  - lib/msfl/parsers/json.rb
121
122
  - lib/msfl/sinatra.rb
@@ -146,17 +147,17 @@ require_paths:
146
147
  - lib
147
148
  required_ruby_version: !ruby/object:Gem::Requirement
148
149
  requirements:
149
- - - '>='
150
+ - - ">="
150
151
  - !ruby/object:Gem::Version
151
152
  version: '0'
152
153
  required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  requirements:
154
- - - '>='
155
+ - - ">"
155
156
  - !ruby/object:Gem::Version
156
- version: '0'
157
+ version: 1.3.1
157
158
  requirements: []
158
159
  rubyforge_project:
159
- rubygems_version: 2.4.2
160
+ rubygems_version: 2.2.2
160
161
  signing_key:
161
162
  specification_version: 4
162
163
  summary: MSFL in Ruby