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,3 @@
1
+ module Cullender
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,66 @@
1
+ require 'generators/cullender/orm_helpers'
2
+
3
+ module Cullender
4
+ module Generators
5
+ class CullenderGenerator < Rails::Generators::NamedBase
6
+ include Rails::Generators::Migration
7
+ include Cullender::Generators::OrmHelpers
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
11
+ desc "Generates a model with the given NAME (if one does not exist) with cullender " <<
12
+ "configuration plus a migration file and cullender routes."
13
+
14
+ class_option :routes, :desc => "Generate routes", :type => :boolean, :default => true
15
+
16
+
17
+ def add_cullender_routes
18
+ cullender_route = "cullender_for :#{plural_name}"
19
+ cullender_route << %Q(, :class_name => "#{class_name}") if class_name.include?("::")
20
+ cullender_route << %Q(, :skip => :all) unless options.routes?
21
+ route cullender_route
22
+ end
23
+
24
+
25
+ def copy_cullender_rules_migration
26
+ migration_template "cullender_migration.rb", "db/migrate/create_cullender_tables"
27
+ end
28
+
29
+ # def copy_cullender_migration
30
+ # if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
31
+ # migration_template "migration_existing.rb", "db/migrate/add_cullender_to_#{table_name}"
32
+ # else
33
+ # migration_template "migration.rb", "db/migrate/create_cullender_for_#{table_name}"
34
+ # end
35
+ # end
36
+
37
+ # def inject_cullender_content
38
+ # content = model_contents + <<CONTENT
39
+ # # Setup accessible (or protected) attributes for your model
40
+ # attr_accessible :email, :password, :password_confirmation, :remember_me
41
+ # CONTENT
42
+
43
+ # class_path = if namespaced?
44
+ # class_name.to_s.split("::")
45
+ # else
46
+ # [class_name]
47
+ # end
48
+
49
+ # indent_depth = class_path.size - 1
50
+ # content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
51
+
52
+ # inject_into_class(model_path, class_path.last, content) if model_exists?
53
+ # end
54
+
55
+
56
+ def migration_data
57
+ <<RUBY
58
+ t.string :name
59
+ t.boolean :enabled
60
+ t.text :triggers
61
+ RUBY
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,18 @@
1
+ module Cullender
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ desc "Creates a Cullender initializer and copy locale files to your application."
7
+
8
+
9
+ def create_initializer_file
10
+ template "cullender.rb", "config/initializers/cullender.rb"
11
+ end
12
+
13
+ def copy_locale
14
+ copy_file "../../../../config/locales/en.yml", "config/locales/cullender.en.yml"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ module Cullender
2
+ module Generators
3
+ module OrmHelpers
4
+ def model_contents
5
+ <<-CONTENT
6
+ # Include default devise modules. Others available are:
7
+ # :token_authenticatable, :confirmable,
8
+ # :lockable, :timeoutable and :omniauthable
9
+ devise :database_authenticatable, :registerable,
10
+ :recoverable, :rememberable, :trackable, :validatable
11
+
12
+ CONTENT
13
+ end
14
+
15
+ def model_exists?
16
+ File.exists?(File.join(destination_root, model_path))
17
+ end
18
+
19
+ def migration_exists?(table_name)
20
+ Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
21
+ end
22
+
23
+ def migration_path
24
+ @migration_path ||= File.join("db", "migrate")
25
+ end
26
+
27
+ def model_path
28
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ Cullender.setup do |config|
2
+
3
+ end
@@ -0,0 +1,13 @@
1
+ class CreateCullenderTables < ActiveRecord::Migration
2
+ def change
3
+ create_table :rules do |t|
4
+ <%= migration_data -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :cullender do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ # This spec was generated by rspec-rails when you ran the scaffold generator.
4
+ # It demonstrates how one might use RSpec to specify the controller code that
5
+ # was generated by Rails when you ran the scaffold generator.
6
+ #
7
+ # It assumes that the implementation code is generated by the rails scaffold
8
+ # generator. If you are using any extension libraries to generate different
9
+ # controller code, this generated spec may or may not pass.
10
+ #
11
+ # It only uses APIs available in rails and/or rspec-rails. There are a number
12
+ # of tools you can use to make these specs even more expressive, but we're
13
+ # sticking to rails and rspec-rails APIs to keep things simple and stable.
14
+ #
15
+ # Compared to earlier versions of this generator, there is very limited use of
16
+ # stubs and message expectations in this spec. Stubs are only used when there
17
+ # is no simpler way to get a handle on the object needed for the example.
18
+ # Message expectations are only used when there is no simpler way to specify
19
+ # that an instance is receiving a specific message.
20
+
21
+ describe Cullender::RulesController do
22
+ before(:each) do
23
+ @request.env["cullender.mapping"] = Cullender.mappings[:event]
24
+ Cullender::Rule.reset_callbacks(:create)
25
+ end
26
+ # This should return the minimal set of attributes required to create a valid
27
+ # Rule. As you add validations to Rule, be sure to
28
+ # update the return value of this method accordingly.
29
+ def valid_attributes
30
+ {name: "MyRule"}
31
+ end
32
+
33
+ # This should return the minimal set of values that should be in the session
34
+ # in order to pass any filters (e.g. authentication) defined in
35
+ # RulesController. Be sure to keep this updated too.
36
+ def valid_session
37
+ {}
38
+ end
39
+
40
+ describe "GET index" do
41
+ before(:each) do
42
+ @rule = Cullender::Rule.create(valid_attributes)
43
+ get :index, {:use_route => :cullender}, valid_session
44
+ end
45
+
46
+ it "assigns all rules as @rules" do
47
+ assigns(:rules).should eq([@rule])
48
+ end
49
+
50
+ end
51
+
52
+
53
+ describe "GET new" do
54
+ it "assigns a new rule as @rule" do
55
+ get :new, {:use_route => :cullender}, valid_session
56
+ assigns(:rule).should be_a_new(Cullender::Rule)
57
+ end
58
+ end
59
+
60
+ describe "GET show" do
61
+ it "assigns the requested rule as @rule" do
62
+ rule = Cullender::Rule.create(valid_attributes)
63
+ get :show, {:id => rule.to_param, :use_route => :cullender}, valid_session
64
+ assigns(:rule).should eq(rule)
65
+ end
66
+ end
67
+
68
+ describe "POST create" do
69
+ context "with valid params" do
70
+ it "creates a new Rule" do
71
+ expect {
72
+ post :create, {:rule => valid_attributes, :use_route => :cullender}, valid_session
73
+ }.to change(Cullender::Rule, :count).by(1)
74
+ end
75
+
76
+ it "assigns a newly created rule as @rule" do
77
+ post :create, {:rule => valid_attributes, :use_route => :cullender}, valid_session
78
+ assigns(:rule).should be_a(Cullender::Rule)
79
+ assigns(:rule).should be_persisted
80
+ end
81
+
82
+ it "redirects to the rules_url" do
83
+ post :create, {:rule => valid_attributes, :use_route => :cullender}, valid_session
84
+ response.should redirect_to({"controller"=>controller.params[:controller], "action"=>"index", :use_route => :cullender})
85
+ end
86
+ end
87
+
88
+ context "with invalid params" do
89
+ it "assigns a newly created but unsaved rule as @rule" do
90
+ # Trigger the behavior that occurs when invalid params are submitted
91
+ Cullender::Rule.any_instance.stub(:save).and_return(false)
92
+ post :create, {:rule => {:name => "asd"}, :use_route => :cullender}, valid_session
93
+ assigns(:rule).should be_a_new(Cullender::Rule)
94
+ end
95
+
96
+ it "re-renders the 'new' template" do
97
+ # Trigger the behavior that occurs when invalid params are submitted
98
+ Cullender::Rule.any_instance.stub(:save).and_return(false)
99
+ post :create, {:rule => {:name => "asd"}, :use_route => :cullender}, valid_session
100
+ response.should render_template("new")
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "PUT update" do
106
+ before(:each) do
107
+ controller.stub(:clean_ids).and_return(nil)
108
+ Cullender::Rule.reset_callbacks(:update)
109
+ end
110
+ context "with valid params" do
111
+ it "updates the requested rule" do
112
+ rule = Cullender::Rule.create(valid_attributes)
113
+ # Assuming there are no other rules in the database, this
114
+ # specifies that the Rule created on the previous line
115
+ # receives the :update_attributes message with whatever params are
116
+ # submitted in the request.
117
+
118
+ Cullender::Rule.any_instance.should_receive(:update_attributes).with({'name' => 'New Name'})
119
+ put :update, {:id => rule.to_param, :rule => {'name' => 'New Name'}, :use_route => :cullender}, valid_session
120
+ end
121
+
122
+ it "assigns the requested rule as @rule" do
123
+ rule = Cullender::Rule.create(valid_attributes)
124
+ put :update, {:id => rule.to_param, :rule => valid_attributes, :use_route => :cullender}, valid_session
125
+ assigns(:rule).should eq(rule)
126
+ end
127
+
128
+ it "redirects to the rules page" do
129
+ rule = Cullender::Rule.create(valid_attributes)
130
+ put :update, {:id => rule.to_param, :rule => valid_attributes, :use_route => :cullender}, valid_session
131
+ response.should redirect_to({"controller"=>controller.params[:controller], "action"=>"index", :use_route => :cullender})
132
+ end
133
+ end
134
+
135
+ context "with invalid params" do
136
+ it "assigns the rule as @rule" do
137
+ rule = Cullender::Rule.create(valid_attributes)
138
+ # Trigger the behavior that occurs when invalid params are submitted
139
+ Cullender::Rule.any_instance.stub(:save).and_return(false)
140
+ put :update, {:id => rule.to_param, :rule => {:name => "asd"}, :use_route => :cullender}, valid_session
141
+ assigns(:rule).should eq(rule)
142
+ end
143
+
144
+ it "re-renders the 'show' template" do
145
+ rule = Cullender::Rule.create(valid_attributes)
146
+ # Trigger the behavior that occurs when invalid params are submitted
147
+ Cullender::Rule.any_instance.stub(:save).and_return(false)
148
+ put :update, {:id => rule.to_param, :rule => {:name => "asd"}, :use_route => :cullender}, valid_session
149
+ response.should render_template("show")
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "DELETE destroy" do
155
+ before(:each)do
156
+ @factory = Cullender::Rule.create(valid_attributes)
157
+ Cullender::Rule.reset_callbacks(:destroy)
158
+ end
159
+ it "destroys the requested model" do
160
+ expect {
161
+ delete :destroy, {:id => @factory.to_param, :use_route => :cullender}, valid_session
162
+ }.to change(@factory.class, :count).by(-1)
163
+ end
164
+
165
+ it "redirects to the index url" do
166
+ delete :destroy, {:id => @factory.to_param, :use_route => :cullender}, valid_session
167
+ if defined?(@redirect)
168
+ response.should redirect_to(@redirect)
169
+ else
170
+ response.should redirect_to({"controller"=>controller.params[:controller], "action"=>"index", :use_route => :cullender})
171
+ end
172
+ end
173
+
174
+ it "returns a flash message that says that the model has been destroyed" do
175
+ delete :destroy, {:id => @factory.to_param, :use_route => :cullender}, valid_session
176
+ controller.flash[:notice].should eql("Rule was successfully destroyed.")
177
+ end
178
+ end
179
+
180
+ end
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Cullender::Controllers::FilterLogic" do
4
+
5
+ before(:each) do
6
+ @object = Object.new
7
+ @object.extend(Cullender::Controllers::FilterLogic)
8
+ end
9
+
10
+
11
+ def add_or_filter(key, params, field, should_raise = false)
12
+ if params.present? && params.has_key?(key)
13
+ if should_raise
14
+ params[key] = {1 => params[key], 2 => add_operator(field)}
15
+ else
16
+ idx = params[key].keys.last.to_i + 1
17
+ params[key].deep_merge!({idx => add_operator(field)})
18
+ end
19
+ else
20
+ if should_raise
21
+ params[key] = add_operator(field)
22
+ else
23
+ params[key] = add_operator(field)
24
+ end
25
+ end
26
+ end
27
+ describe "#add_or_filter" do
28
+ context "with filter(s) defined" do
29
+ context "OR with the base" do
30
+ context "with only one group" do
31
+ before(:each) do
32
+ @hash = {"f" => {"some_field" => {"o" => nil}}}
33
+ @object.add_or_filter("f", @hash, "new_field", true)
34
+ end
35
+ it "moves the existing group to a higher level" do
36
+ @hash["f"].should have_key(1)
37
+ @hash["f"][1].should have_key("some_field")
38
+ end
39
+ it "adds the filter to a new group" do
40
+ @hash["f"].should have_key(2)
41
+ @hash["f"][2].should have_key("new_field")
42
+ end
43
+ end
44
+ context "with many groups" do
45
+ before(:each) do
46
+ @hash = {"f" => {1 => {"some_field1" => {"o" => nil}}, 2 => {"some_field2" => {"o" => nil}}}}
47
+ @object.add_or_filter("f", @hash, "new_field", true)
48
+ end
49
+ it "moves the existing group to a higher level" do
50
+ @hash["f"].should have_key(1)
51
+ @hash["f"][1][1].should have_key("some_field1")
52
+ @hash["f"][1][2].should have_key("some_field2")
53
+ end
54
+ it "adds the filter to a new group" do
55
+ @hash["f"].should have_key(2)
56
+ @hash["f"][2].should have_key("new_field")
57
+ end
58
+ end
59
+ end
60
+ context "OR with other groups at the same level" do
61
+ before(:each) do
62
+ @hash = {"f" => {1 => {"some_field1" => {"o" => nil}}, 2 => {"some_field2" => {"o" => nil}}}}
63
+ @object.add_or_filter("f", @hash, "new_field", false)
64
+ end
65
+ it "keeps the existing group at the higher level" do
66
+ @hash["f"].should have_key(1)
67
+ @hash["f"][1].should have_key("some_field1")
68
+ @hash["f"][2].should have_key("some_field2")
69
+ end
70
+ it "adds the filter to as a new group" do
71
+ @hash["f"].should have_key(3)
72
+ @hash["f"][3].should have_key("new_field")
73
+ end
74
+ end
75
+ end
76
+ context "with filter(s) undefined" do
77
+ before(:each) do
78
+ @hash = {}
79
+ @object.add_or_filter("f", @hash, "my_field")
80
+ end
81
+ it "creates a new filter hash with the field" do
82
+ @hash.should have_key("f")
83
+ @hash["f"].should have_key("my_field")
84
+ end
85
+ end
86
+ end
87
+
88
+ # def add_and_filter(params, field)
89
+ # if params.has_key?("f")
90
+ # params["f"].deep_merge!(add_operator(field))
91
+ # else
92
+ # params["f"] = add_operator(field)
93
+ # end
94
+ # end
95
+ describe "#add_and_filter" do
96
+ context "with existing filter(s)" do
97
+ context "that are deeply nested" do
98
+ before(:each) do
99
+ @params = { "f" => {1 => {"field1" => {"o" => nil}, "field2" => {"o" => nil}}, 2 => {1 => {"field3" => {"o" => nil}}}, "field4" => {"o" => nil}}}
100
+ end
101
+ it "adds a new field with 1 deep if the key doesn't exist" do
102
+ @object.add_and_filter("f", @params, { 1 => "field3"})
103
+ @params["f"][1].should have(3).keys
104
+ @params["f"][1].should have_key("field3")
105
+ end
106
+ it "adds a new field with 2 deep if the key doesn't exist" do
107
+ @object.add_and_filter( "f", @params, {2 => {1 => "field2"}})
108
+ @params["f"][2][1].should have(2).keys
109
+ @params["f"][2][1].should have_key("field2")
110
+ end
111
+ it "doesn't add a new field if the key already exists" do
112
+ @object.add_and_filter("f", @params, { 1 => "field2"})
113
+ @params["f"][1].should have(2).keys
114
+ end
115
+ end
116
+ context "that are not nested" do
117
+ before(:each) do
118
+ @params = { "f" => {"field1" => {"o" => nil}, "field2" => {"o" => nil}}}
119
+ end
120
+ it "adds a new field if the key doesn't exist" do
121
+ @object.add_and_filter("f", @params, "field3")
122
+ @params["f"].should have(3).keys
123
+ @params["f"].should have_key("field3")
124
+ end
125
+ end
126
+ end
127
+ context "without existing filter(s)" do
128
+ before(:each) do
129
+ @hash = {}
130
+ @object.add_and_filter("f", @hash, "my_field")
131
+ end
132
+ it "creates a new filter hash with the field" do
133
+ @hash.should have_key("f")
134
+ @hash["f"].should have_key("my_field")
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "#remove_and_filter" do
140
+ context "with a filter present" do
141
+ it "deletes the part of hash specified by a string" do
142
+ params = {"f" => {"field" => {"o" => nil}}}
143
+ params["f"].should_receive(:delete).with("field")
144
+ @object.remove_and_filter("f", params, "field")
145
+ end
146
+ it "deletes the part of hash specified by a hash" do
147
+ params = {"f" => { 1 => {"field" => {"o" => nil}}}}
148
+ params["f"].should_receive(:deep_delete).with({1 => {"field" => nil}})
149
+ @object.remove_and_filter("f", params, {1 => {"field" => nil}})
150
+ end
151
+ end
152
+ context "without a filter present" do
153
+ it "does nothing" do
154
+ params = {"f" => {"field" => {"o" => nil}}}
155
+ params.stub(:has_key?).with("f").and_return(false)
156
+ params["f"].should_not_receive(:deep_delete)
157
+ @object.remove_and_filter("f", params, "field")
158
+ end
159
+ end
160
+ end
161
+
162
+
163
+ describe "#add_operator" do
164
+ it "returns a hash with an operator indexed by the specified string" do
165
+ @object.add_operator("index").should eql({"index" => {"o" => nil}})
166
+ end
167
+ it "returns a hash with an operator indexed by the specified hash" do
168
+ @object.add_operator({0 => "index"}).should eql({0 => {"index" => {"o" => nil}}})
169
+ end
170
+ end
171
+
172
+ describe "#apply_filter_actions" do
173
+ context "add OR" do
174
+ context "with no params" do
175
+ it "raise new field", :current => true do
176
+ params = {"or"=>{"raise_field"=>"name", "raise"=>"OR"}}
177
+ flag = @object.apply_filter_actions("triggers", {"name" => "dsafdasg"}, params)
178
+ flag.should be_true
179
+ end
180
+ end
181
+ context "with 'field' present" do
182
+ before(:each) do
183
+ @params = {"or" => {"field" => "myfield", "commit" => "OR"}}
184
+ end
185
+ it "adds an or filter" do
186
+ @object.should_receive(:add_or_filter).with("name", {"name" => {}}, "myfield", false)
187
+ @object.apply_filter_actions("name", {"name" => {}}, @params)
188
+ end
189
+ end
190
+ context "without 'field' present" do
191
+ before(:each) do
192
+ @params = {"or" => {"field" => nil, "commit" => "OR"}}
193
+ end
194
+ it "does not add an or filter" do
195
+ @object.should_not_receive(:add_or_filter)
196
+ @object.apply_filter_actions("name", {"name" => {}}, @params)
197
+ end
198
+ end
199
+ end
200
+ context "add AND" do
201
+ context "with 'field' present" do
202
+ context "with 'field' present" do
203
+ before(:each) do
204
+ @params = {"and" => {"field" => "myfield", "commit" => "AND"}}
205
+ end
206
+ it "adds an or filter" do
207
+ @object.should_receive(:add_and_filter).with("name", {"name" => {}}, "myfield")
208
+ @object.apply_filter_actions("name", {"name" => {}}, @params)
209
+ end
210
+ end
211
+ context "without 'field' present" do
212
+ before(:each) do
213
+ @params = {"and" => {"field" => nil, "commit" => "OR"}}
214
+ end
215
+ it "does not add an or filter" do
216
+ @object.should_not_receive(:add_and_filter)
217
+ @object.apply_filter_actions("name", {"name" => {}}, @params)
218
+ end
219
+ end
220
+ end
221
+ end
222
+ context "remove" do
223
+ before(:each) do
224
+ @params = {"remove" => "myfield"}
225
+ end
226
+ it "adds an or filter" do
227
+ @object.should_receive(:remove_and_filter).with("name", {"name" => {}}, "myfield")
228
+ @object.apply_filter_actions("name", {"name" => {}}, @params)
229
+ end
230
+ end
231
+ end
232
+
233
+ end