cullender 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/cullender/application.js +13 -0
  6. data/app/assets/javascripts/cullender/rules.js +46 -0
  7. data/app/assets/stylesheets/cullender/application.css +13 -0
  8. data/app/assets/stylesheets/cullender/rules.css.scss +15 -0
  9. data/app/controllers/cullender/rules_controller.rb +68 -0
  10. data/app/controllers/cullender_controller.rb +105 -0
  11. data/app/helpers/cullender/rules_helper.rb +136 -0
  12. data/app/models/cullender/rule.rb +204 -0
  13. data/app/views/cullender/rules/_form.html.erb +20 -0
  14. data/app/views/cullender/rules/_trigger_fields.html.erb +19 -0
  15. data/app/views/cullender/rules/create.js.erb +3 -0
  16. data/app/views/cullender/rules/index.html.erb +25 -0
  17. data/app/views/cullender/rules/new.html.erb +1 -0
  18. data/app/views/cullender/rules/show.html.erb +3 -0
  19. data/config/locales/en.yml +12 -0
  20. data/config/routes.rb +4 -0
  21. data/lib/cullender.rb +96 -0
  22. data/lib/cullender/controllers/filter_logic.rb +89 -0
  23. data/lib/cullender/controllers/scoped_views.rb +17 -0
  24. data/lib/cullender/core_ext/hash.rb +1 -0
  25. data/lib/cullender/core_ext/hash/deep_delete.rb +13 -0
  26. data/lib/cullender/engine.rb +15 -0
  27. data/lib/cullender/engine/routes.rb +306 -0
  28. data/lib/cullender/mapping.rb +139 -0
  29. data/lib/cullender/version.rb +3 -0
  30. data/lib/generators/cullender/cullender_generator.rb +66 -0
  31. data/lib/generators/cullender/install_generator.rb +18 -0
  32. data/lib/generators/cullender/orm_helpers.rb +32 -0
  33. data/lib/generators/cullender/templates/cullender.rb +3 -0
  34. data/lib/generators/cullender/templates/cullender_migration.rb +13 -0
  35. data/lib/tasks/cullender_tasks.rake +4 -0
  36. data/spec/controllers/cullender/rules_controller_spec.rb +180 -0
  37. data/spec/cullender/controllers/filter_logic_spec.rb +233 -0
  38. data/spec/dummy/README.rdoc +28 -0
  39. data/spec/dummy/Rakefile +6 -0
  40. data/spec/dummy/app/assets/javascripts/application.js +17 -0
  41. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  42. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  43. data/spec/dummy/app/controllers/events_controller.rb +60 -0
  44. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  45. data/spec/dummy/app/models/event.rb +16 -0
  46. data/spec/dummy/app/views/cullender/rules/_form.html.erb +33 -0
  47. data/spec/dummy/app/views/cullender/rules/index.html.erb +24 -0
  48. data/spec/dummy/app/views/cullender/rules/new.html.erb +1 -0
  49. data/spec/dummy/app/views/cullender/rules/show.html.erb +3 -0
  50. data/spec/dummy/app/views/events/_form.html.erb +21 -0
  51. data/spec/dummy/app/views/events/edit.html.erb +6 -0
  52. data/spec/dummy/app/views/events/index.html.erb +27 -0
  53. data/spec/dummy/app/views/events/new.html.erb +5 -0
  54. data/spec/dummy/app/views/events/show.html.erb +10 -0
  55. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  56. data/spec/dummy/bin/bundle +3 -0
  57. data/spec/dummy/bin/rails +4 -0
  58. data/spec/dummy/bin/rake +4 -0
  59. data/spec/dummy/config.ru +4 -0
  60. data/spec/dummy/config/application.rb +23 -0
  61. data/spec/dummy/config/boot.rb +9 -0
  62. data/spec/dummy/config/database.yml +25 -0
  63. data/spec/dummy/config/environment.rb +5 -0
  64. data/spec/dummy/config/environments/development.rb +27 -0
  65. data/spec/dummy/config/environments/production.rb +80 -0
  66. data/spec/dummy/config/environments/test.rb +36 -0
  67. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/dummy/config/initializers/cullender.rb +3 -0
  69. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/spec/dummy/config/initializers/inflections.rb +16 -0
  71. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  72. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  73. data/spec/dummy/config/initializers/session_store.rb +3 -0
  74. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  75. data/spec/dummy/config/locales/cullender.en.yml +12 -0
  76. data/spec/dummy/config/locales/en.yml +23 -0
  77. data/spec/dummy/config/routes.rb +5 -0
  78. data/spec/dummy/db/development.sqlite3 +0 -0
  79. data/spec/dummy/db/migrate/123344556676_create_cullender_tables.rb +12 -0
  80. data/spec/dummy/db/schema.rb +24 -0
  81. data/spec/dummy/db/test.sqlite3 +0 -0
  82. data/spec/dummy/log/development.log +9987 -0
  83. data/spec/dummy/log/test.log +19786 -0
  84. data/spec/dummy/public/404.html +27 -0
  85. data/spec/dummy/public/422.html +26 -0
  86. data/spec/dummy/public/500.html +26 -0
  87. data/spec/dummy/public/favicon.ico +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/268a828ee4997cf5c19106e5f00fcfb8 +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/56b2eb9b46b9aca7e86b5132ddf0d9de +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/750887406b3e8dacb2b03f986330932d +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/750b42e431d194c41f5b1cde4a257e47 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/921642fe740290e9e5e88a706e5a562c +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/a967ed3fc5f8406f3ff72180775f1b40 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/ae74bf4fc3fd20e7f7b98860b8ef0f74 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/c7dbd1f5acc2d5bc078363f4f3c70c54 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/d995daf8d6f36c27b6e9d1b4672eaf1e +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  103. data/spec/helpers/cullender/rules_helper_spec.rb +360 -0
  104. data/spec/models/cullender/rule_spec.rb +425 -0
  105. data/spec/requests/rules_spec.rb +19 -0
  106. data/spec/spec_helper.rb +60 -0
  107. metadata +319 -0
@@ -0,0 +1,425 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cullender::Rule do
4
+
5
+ # describe "#fire" do
6
+ # before(:each) do
7
+ # @rule = Rule.new
8
+ # end
9
+ # context "with events" do
10
+ # before(:each) do
11
+ # @event = Factory(:event)
12
+ # Event.stub(:filter_between).with(nil, nil, @rule.triggers).and_return([@event])
13
+ # end
14
+ # context "with labels" do
15
+ # before(:each) do
16
+ # @rule.labels = ["label1", "label2"]
17
+ # end
18
+ # it "adds labels to the events" do
19
+ # @rule.fire(nil, nil)
20
+ # @event.should have(2).tags
21
+ # @event.tags.should include "label1"
22
+ # @event.tags.should include "label2"
23
+ # end
24
+ # end
25
+ # end
26
+ # context "with no events" do
27
+ # before(:each) do
28
+ # Event.stub(:filter_between).with(nil, nil, @rule.triggers).and_return([])
29
+ # end
30
+ # it "returns nil" do
31
+ # @rule.fire(nil, nil).should be_nil
32
+ # end
33
+ # end
34
+ # end
35
+
36
+ def single_attr(key = "attr", value = 100)
37
+ {key => {"o" => "term", "v" => value}}
38
+ end
39
+
40
+
41
+ describe ".to_query_proc" do
42
+ before(:each) do
43
+ @rule = Cullender::Rule.new
44
+ end
45
+ it "returns a Proc object" do
46
+ # @rule.should_receive(:to_query).and_return(::Tire::Search::Query.new)
47
+ query_proc = @rule.to_query_proc
48
+ query_proc.should be_a_kind_of(Proc)
49
+ end
50
+ end
51
+
52
+
53
+ describe "#number_of_fields" do
54
+ before(:each) do
55
+ @rule = Cullender::Rule.new
56
+ end
57
+ context "with triggers not set" do
58
+ it "returns 0" do
59
+ @rule.send(:number_of_fields).should == 0
60
+ end
61
+ end
62
+ context "single level" do
63
+ context "single field" do
64
+ before(:each) do
65
+ @rule.triggers = single_attr
66
+ end
67
+ it "returns the count" do
68
+ @rule.send(:number_of_fields).should == 1
69
+ end
70
+ end
71
+
72
+ context "multiple fields" do
73
+ before(:each) do
74
+ @rule.triggers = single_attr("attr1", 100).merge!(single_attr("attr2", 200))
75
+ end
76
+ it "returns the count" do
77
+ @rule.send(:number_of_fields).should == 2
78
+ end
79
+ end
80
+ end
81
+ context "deep nesting" do
82
+ context "single level" do
83
+ before(:each) do
84
+ @rule.triggers = {
85
+ "1" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
86
+ "2" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
87
+ }
88
+ end
89
+ it "returns the count" do
90
+ @rule.send(:number_of_fields).should == 4
91
+ end
92
+ end
93
+ context "different levels" do
94
+ before(:each) do
95
+ @rule.triggers = {
96
+ "1" => {
97
+ "1" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
98
+ "2" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
99
+ },
100
+ "2" => single_attr("attr5", 500).merge!(single_attr("attr6", 600)),
101
+ "3" => single_attr("attr7", 700).merge!(single_attr("attr8", 800))
102
+ }
103
+ end
104
+ it "returns the count" do
105
+ @rule.send(:number_of_fields).should == 8
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+
112
+
113
+ describe "#to_query", :current => true do
114
+ before(:each) do
115
+ @rule = Cullender::Rule.new
116
+ end
117
+ context "a single attr" do
118
+ before(:each) do
119
+ @rule.triggers = single_attr
120
+ end
121
+ it "parses the filter for matching" do
122
+ result = @rule.to_query.to_hash
123
+ result.should == {
124
+ :term => {
125
+ "attr" => {:term => 100}
126
+ }
127
+ }
128
+ end
129
+ end
130
+
131
+ context "multiple filter 'AND'ed together" do
132
+ before(:each) do
133
+ @rule.triggers = single_attr("attr1", 100).merge!(single_attr("attr2", 200))
134
+ end
135
+ it "parses the filter for matching" do
136
+ result = @rule.to_query.to_hash
137
+ result.should == {:bool=>{:must=>[{:term=>{"attr1"=>{:term=>100}}}, {:term=>{"attr2"=>{:term=>200}}}]}}
138
+ # {
139
+ # :filtered => {
140
+ # :filter => {
141
+ # :and => [
142
+ # {:term => {:attr1 => "100"}},
143
+ # {:term => {:attr2 => "200"}}
144
+ # ]
145
+ # }
146
+ # }
147
+ # }
148
+ end
149
+ end
150
+
151
+ context "multiple 'AND'ed filters 'OR'ed together" do
152
+ before(:each) do
153
+ @rule.triggers = {
154
+ "1" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
155
+ "2" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
156
+ }
157
+ end
158
+ it "parses the filter for matching" do
159
+ result = @rule.to_query.to_hash
160
+ result.should == {
161
+ :bool=>{
162
+ :should=>[
163
+ {
164
+ :bool=>{
165
+ :must=>[
166
+ {:term=>{"attr1"=>{:term=>100}}},
167
+ {:term=>{"attr2"=>{:term=>200}}}
168
+ ]
169
+ }
170
+ },{
171
+ :bool=>{
172
+ :must=>[
173
+ {:term=>{"attr3"=>{:term=>300}}},
174
+ {:term=>{"attr4"=>{:term=>400}}}
175
+ ]
176
+ }
177
+ }
178
+ ]
179
+ }
180
+ }
181
+
182
+ # {
183
+ # :filtered => {
184
+ # :filter => {
185
+ # :and => [
186
+ # :or => [
187
+ # {:and => [
188
+ # {:term => {:attr1 => "100"}},
189
+ # {:term => {:attr2 => "200"}}
190
+ # ]},
191
+ # {:and => [
192
+ # {:term => {:attr3 => "300"}},
193
+ # {:term => {:attr4 => "400"}}
194
+ # ]}
195
+ # ]
196
+ # ]
197
+ # }
198
+ # }
199
+ # }
200
+ end
201
+ end
202
+
203
+ context "deeply nested multiple 'AND'ed filters 'OR'ed together" do
204
+ before(:each) do
205
+ @rule.triggers = {
206
+ "1" => {
207
+ "1" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
208
+ "2" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
209
+ },
210
+ "2" => {
211
+ "1" => single_attr("attr5", 500).merge!(single_attr("attr6", 600)),
212
+ "2" => single_attr("attr7", 700).merge!(single_attr("attr8", 800)),
213
+ }
214
+ }
215
+ end
216
+ it "parses the filter for matching" do
217
+ result = @rule.to_query.to_hash
218
+ result.should == {
219
+ :bool=>{
220
+ :should=>[
221
+ {
222
+ :bool=>{
223
+ :should=>[
224
+ {
225
+ :bool=>{
226
+ :must=>[
227
+ {:term=>{"attr1"=>{:term=>100}}},
228
+ {:term=>{"attr2"=>{:term=>200}}}
229
+ ]
230
+ }
231
+ },{
232
+ :bool=>{
233
+ :must=>[
234
+ {:term=>{"attr3"=>{:term=>300}}},
235
+ {:term=>{"attr4"=>{:term=>400}}}
236
+ ]
237
+ }
238
+ }
239
+ ]
240
+ }
241
+ },{
242
+ :bool=>{
243
+ :should=>[
244
+ {
245
+ :bool=>{
246
+ :must=>[
247
+ {:term=>{"attr5"=>{:term=>500}}},
248
+ {:term=>{"attr6"=>{:term=>600}}}
249
+ ]
250
+ }
251
+ },{
252
+ :bool=>{
253
+ :must=>[
254
+ {:term=>{"attr7"=>{:term=>700}}},
255
+ {:term=>{"attr8"=>{:term=>800}}}
256
+ ]
257
+ }
258
+ }
259
+ ]
260
+ }
261
+ }
262
+ ]
263
+ }
264
+ }
265
+ # {
266
+ # :filtered => {
267
+ # :filter => {
268
+ # :and => [
269
+ # :or => [
270
+ # {:or => [
271
+ # {:and => [
272
+ # {:term => {:attr1 => "100"}},
273
+ # {:term => {:attr2 => "200"}}
274
+ # ]},
275
+ # {:and => [
276
+ # {:term => {:attr3 => "300"}},
277
+ # {:term => {:attr4 => "400"}}
278
+ # ]}
279
+ # ]},
280
+ # {:or => [
281
+ # {:and => [
282
+ # {:term => {:attr5 => "500"}},
283
+ # {:term => {:attr6 => "600"}}
284
+ # ]},
285
+ # {:and => [
286
+ # {:term => {:attr7 => "700"}},
287
+ # {:term => {:attr8 => "800"}}
288
+ # ]}
289
+ # ]}
290
+ # ]
291
+ # ]
292
+ # }
293
+ # }
294
+ # }
295
+ end
296
+ end
297
+
298
+ end
299
+
300
+
301
+ # describe "#to_search" do
302
+ # before(:each) do
303
+ # @rule = Cullender::Rule.new
304
+ # end
305
+ # context "a single filter" do
306
+ # before(:each) do
307
+ # @rule.triggers = single_attr
308
+ # end
309
+ # it "parses the filter for matching" do
310
+ # result = @rule.to_search.to_hash
311
+ # result.should == {
312
+ # :filter => {
313
+ # :term => {:attr => "100"}
314
+ # }
315
+ # }
316
+ # end
317
+ # end
318
+
319
+ # context "multiple filter 'AND'ed together" do
320
+ # before(:each) do
321
+ # @rule.triggers = single_attr("attr1", 100).merge!(single_attr("attr2", 200))
322
+ # end
323
+ # it "parses the filter for matching" do
324
+ # result = @rule.to_search.to_hash
325
+ # result.should == {
326
+ # :filter => {
327
+ # :and => [
328
+ # {:term => {:attr1 => "100"}},
329
+ # {:term => {:attr2 => "200"}}
330
+ # ]
331
+ # }
332
+ # }
333
+ # end
334
+ # end
335
+
336
+ # context "multiple 'AND'ed filters 'OR'ed together" do
337
+ # before(:each) do
338
+ # @rule.triggers = {
339
+ # "1" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
340
+ # "2" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
341
+ # }
342
+ # end
343
+ # it "parses the filter for matching" do
344
+ # result = @rule.to_search.to_hash
345
+ # result.should == {
346
+ # :filter => {
347
+ # :or => [
348
+ # {:and => [
349
+ # {:term => {:attr1 => "100"}},
350
+ # {:term => {:attr2 => "200"}}
351
+ # ]},
352
+ # {:and => [
353
+ # {:term => {:attr3 => "300"}},
354
+ # {:term => {:attr4 => "400"}}
355
+ # ]}
356
+ # ]
357
+ # }
358
+ # }
359
+ # end
360
+ # end
361
+
362
+ # context "deeply nested multiple 'AND'ed filters 'OR'ed together" do
363
+ # before(:each) do
364
+ # @rule.triggers = {
365
+ # "1" => {
366
+ # "2" => single_attr("attr1", 100).merge!(single_attr("attr2", 200)),
367
+ # "1" => single_attr("attr3", 300).merge!(single_attr("attr4", 400))
368
+ # },
369
+ # "2" => {
370
+ # "1" => single_attr("attr5", 500).merge!(single_attr("attr6", 600)),
371
+ # "2" => single_attr("attr7", 700).merge!(single_attr("attr8", 800)),
372
+ # }
373
+ # }
374
+ # end
375
+ # it "parses the filter for matching" do
376
+ # result = @rule.to_search.to_hash
377
+ # result.should == {
378
+ # :filter => {
379
+ # :or => [
380
+ # {:or => [
381
+ # {:and => [
382
+ # {:term => {:attr1 => "100"}},
383
+ # {:term => {:attr2 => "200"}}
384
+ # ]},
385
+ # {:and => [
386
+ # {:term => {:attr3 => "300"}},
387
+ # {:term => {:attr4 => "400"}}
388
+ # ]}
389
+ # ]},
390
+ # {:or => [
391
+ # {:and => [
392
+ # {:term => {:attr5 => "500"}},
393
+ # {:term => {:attr6 => "600"}}
394
+ # ]},
395
+ # {:and => [
396
+ # {:term => {:attr7 => "700"}},
397
+ # {:term => {:attr8 => "800"}}
398
+ # ]}
399
+ # ]}
400
+ # ]
401
+ # }
402
+ # }
403
+ # end
404
+ # end
405
+
406
+ # end
407
+
408
+
409
+
410
+
411
+
412
+ end
413
+ # == Schema Information
414
+ #
415
+ # Table name: rules
416
+ #
417
+ # id :integer(4) not null, primary key
418
+ # name :string(255)
419
+ # description :string(255)
420
+ # type :string(255)
421
+ # enabled :boolean(1)
422
+ # created_at :datetime not null
423
+ # updated_at :datetime not null
424
+ #
425
+
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rules" do
4
+
5
+
6
+ describe "POST /rules" do
7
+ context "percolation" do
8
+ before(:each) do
9
+ ::Tire.index('_percolator').refresh
10
+ end
11
+ # test the creating of a rule and percolate command in elasticsearch
12
+ it "works! (now write some real specs)" do
13
+ Cullender::Rule.create(:name => "example", :triggers => {})
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,60 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rails/test_help"
6
+ require 'rspec/rails'
7
+ require 'rspec/autorun'
8
+ require 'capybara/rspec'
9
+ # require 'database_cleaner'
10
+
11
+ Rails.backtrace_cleaner.remove_silencers!
12
+
13
+ # Load support files
14
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
15
+
16
+ RSpec.configure do |config|
17
+
18
+ # == Mock Framework
19
+ #
20
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
21
+ #
22
+ # config.mock_with :mocha
23
+ # config.mock_with :flexmock
24
+ # config.mock_with :rr
25
+ config.mock_with :rspec
26
+
27
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
28
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
29
+
30
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
31
+ # examples within a transaction, remove the following line or assign false
32
+ # instead of true.
33
+ config.use_transactional_fixtures = false
34
+
35
+ # If true, the base class of anonymous controllers will be inferred
36
+ # automatically. This will be the default behavior in future versions of
37
+ # rspec-rails.
38
+ config.infer_base_class_for_anonymous_controllers = false
39
+
40
+
41
+ config.around do |example|
42
+ ActiveRecord::Base.transaction do
43
+ example.run
44
+ raise ActiveRecord::Rollback
45
+ end
46
+ end
47
+
48
+ # config.before(:suite) do
49
+ # DatabaseCleaner.strategy = :transaction
50
+ # DatabaseCleaner.clean_with(:truncation)
51
+ # end
52
+
53
+ # config.before(:each) do
54
+ # DatabaseCleaner.start
55
+ # end
56
+
57
+ # config.after(:each) do
58
+ # DatabaseCleaner.clean
59
+ # end
60
+ end