paloma 2.0.6 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/Changelog.md +3 -75
  2. data/README.md +89 -376
  3. data/TODO.md +1 -13
  4. data/app/views/paloma/_hook.html.erb +31 -0
  5. data/lib/paloma.rb +1 -25
  6. data/lib/paloma/action_controller_extension.rb +72 -38
  7. data/paloma.gemspec +7 -7
  8. data/{spec/test_app → test_app}/.gitignore +0 -0
  9. data/{spec/test_app → test_app}/.rspec +0 -0
  10. data/{spec/test_app → test_app}/Gemfile +1 -2
  11. data/{spec/test_app → test_app}/README.rdoc +0 -0
  12. data/{spec/test_app → test_app}/Rakefile +2 -7
  13. data/test_app/app/assets/images/rails.png +0 -0
  14. data/test_app/app/assets/javascripts/admin/bar.js +2 -0
  15. data/test_app/app/assets/javascripts/application.js +83 -0
  16. data/test_app/app/assets/javascripts/foo.js +2 -0
  17. data/test_app/app/assets/javascripts/main.js +2 -0
  18. data/test_app/app/assets/stylesheets/admin/bar.css +4 -0
  19. data/test_app/app/assets/stylesheets/application.css +13 -0
  20. data/test_app/app/assets/stylesheets/foo.css +4 -0
  21. data/test_app/app/assets/stylesheets/main.css +4 -0
  22. data/test_app/app/controllers/admin/bar_controller.rb +7 -0
  23. data/{spec/test_app → test_app}/app/controllers/application_controller.rb +0 -0
  24. data/test_app/app/controllers/foo_controller.rb +19 -0
  25. data/test_app/app/controllers/main_controller.rb +7 -0
  26. data/test_app/app/helpers/admin/bar_helper.rb +2 -0
  27. data/test_app/app/helpers/application_helper.rb +2 -0
  28. data/test_app/app/helpers/foo_helper.rb +2 -0
  29. data/test_app/app/helpers/main_helper.rb +2 -0
  30. data/{spec/test_app/log → test_app/app/mailers}/.gitkeep +0 -0
  31. data/{spec/test_app/public/favicon.ico → test_app/app/models/.gitkeep} +0 -0
  32. data/test_app/app/views/layouts/application.html.erb +14 -0
  33. data/{spec/test_app → test_app}/config.ru +0 -0
  34. data/{spec/test_app → test_app}/config/application.rb +2 -7
  35. data/{spec/test_app → test_app}/config/boot.rb +0 -0
  36. data/{spec/test_app → test_app}/config/environment.rb +0 -0
  37. data/{spec/test_app → test_app}/config/environments/development.rb +6 -0
  38. data/{spec/test_app → test_app}/config/environments/production.rb +3 -0
  39. data/{spec/test_app → test_app}/config/environments/test.rb +2 -0
  40. data/{spec/test_app → test_app}/config/initializers/backtrace_silencers.rb +0 -0
  41. data/{spec/test_app → test_app}/config/initializers/inflections.rb +0 -0
  42. data/{spec/test_app → test_app}/config/initializers/mime_types.rb +0 -0
  43. data/{spec/test_app → test_app}/config/initializers/secret_token.rb +1 -1
  44. data/{spec/test_app → test_app}/config/initializers/session_store.rb +0 -0
  45. data/{spec/test_app → test_app}/config/initializers/wrap_parameters.rb +4 -0
  46. data/{spec/test_app → test_app}/config/locales/en.yml +0 -0
  47. data/test_app/config/routes.rb +14 -0
  48. data/test_app/db/seeds.rb +7 -0
  49. data/test_app/doc/README_FOR_APP +2 -0
  50. data/test_app/lib/assets/.gitkeep +0 -0
  51. data/test_app/lib/tasks/.gitkeep +0 -0
  52. data/test_app/log/.gitkeep +0 -0
  53. data/{spec/test_app → test_app}/public/404.html +0 -0
  54. data/{spec/test_app → test_app}/public/422.html +0 -0
  55. data/{spec/test_app → test_app}/public/500.html +0 -0
  56. data/test_app/public/favicon.ico +0 -0
  57. data/{spec/test_app → test_app}/public/robots.txt +0 -0
  58. data/{spec/test_app → test_app}/script/rails +0 -0
  59. data/test_app/spec/integration/main_spec.rb +61 -0
  60. data/test_app/spec/javascripts/controller_builder_spec.js +48 -0
  61. data/test_app/spec/javascripts/router_spec.js +121 -0
  62. data/test_app/spec/javascripts/support/jasmine.yml +20 -0
  63. data/{spec/test_app → test_app}/spec/spec_helper.rb +11 -5
  64. data/test_app/test/fixtures/.gitkeep +0 -0
  65. data/test_app/test/functional/.gitkeep +0 -0
  66. data/test_app/test/integration/.gitkeep +0 -0
  67. data/test_app/test/performance/browsing_test.rb +12 -0
  68. data/test_app/test/test_helper.rb +13 -0
  69. data/test_app/test/unit/.gitkeep +0 -0
  70. data/test_app/vendor/assets/javascripts/.gitkeep +0 -0
  71. data/test_app/vendor/assets/stylesheets/.gitkeep +0 -0
  72. data/test_app/vendor/plugins/.gitkeep +0 -0
  73. data/vendor/assets/javascripts/paloma/controller.js +10 -0
  74. data/vendor/assets/javascripts/paloma/controller_builder.js +55 -0
  75. data/vendor/assets/javascripts/paloma/engine.js +61 -0
  76. data/vendor/assets/javascripts/paloma/index.js +6 -0
  77. data/vendor/assets/javascripts/paloma/init.js +1 -0
  78. data/vendor/assets/javascripts/paloma/paloma.js +17 -0
  79. data/vendor/assets/javascripts/paloma/router.js +64 -0
  80. metadata +86 -94
  81. data/app/templates/_filters.js +0 -14
  82. data/app/templates/application/_locals.js +0 -13
  83. data/app/templates/controller/_locals.js +0 -19
  84. data/app/templates/controller/_manifest.js +0 -3
  85. data/app/templates/controller/action.js +0 -23
  86. data/app/templates/index.js +0 -3
  87. data/app/templates/namespace/_locals.js +0 -16
  88. data/app/templates/namespace/_manifest.js +0 -3
  89. data/app/views/paloma/_callback_hook.html.erb +0 -40
  90. data/lib/paloma/action_controller_filters.rb +0 -68
  91. data/lib/paloma/generators/add_generator.rb +0 -136
  92. data/lib/paloma/generators/setup_generator.rb +0 -38
  93. data/lib/paloma/rails/controller_generator.rb +0 -11
  94. data/spec/test_app/app/assets/javascripts/application.js +0 -16
  95. data/spec/test_app/app/assets/javascripts/paloma/_filters.js +0 -130
  96. data/spec/test_app/app/assets/javascripts/paloma/_locals.js +0 -17
  97. data/spec/test_app/app/assets/javascripts/paloma/bar/_filters.js +0 -96
  98. data/spec/test_app/app/assets/javascripts/paloma/bar/_locals.js +0 -1
  99. data/spec/test_app/app/assets/javascripts/paloma/bar/_manifest.js +0 -3
  100. data/spec/test_app/app/assets/javascripts/paloma/bar/another_basic_action.js +0 -5
  101. data/spec/test_app/app/assets/javascripts/paloma/bar/basic_action.js +0 -5
  102. data/spec/test_app/app/assets/javascripts/paloma/bar/different_params.js +0 -4
  103. data/spec/test_app/app/assets/javascripts/paloma/bar/yet_another_basic_action.js +0 -5
  104. data/spec/test_app/app/assets/javascripts/paloma/foo/_filters.js +0 -24
  105. data/spec/test_app/app/assets/javascripts/paloma/foo/_locals.js +0 -21
  106. data/spec/test_app/app/assets/javascripts/paloma/foo/_manifest.js +0 -3
  107. data/spec/test_app/app/assets/javascripts/paloma/foo/basic_action.js +0 -21
  108. data/spec/test_app/app/assets/javascripts/paloma/foo/skip_callback.js +0 -6
  109. data/spec/test_app/app/assets/javascripts/paloma/index.js +0 -6
  110. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/_filters.js +0 -83
  111. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/_manifest.js +0 -2
  112. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/_filters.js +0 -84
  113. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/_locals.js +0 -1
  114. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/_manifest.js +0 -2
  115. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/another_basic_action.js +0 -5
  116. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/basic_action.js +0 -5
  117. data/spec/test_app/app/assets/javascripts/paloma/sample_namespace/baz/yet_another_basic_action.js +0 -5
  118. data/spec/test_app/app/controllers/bar_controller.rb +0 -28
  119. data/spec/test_app/app/controllers/foo_controller.rb +0 -25
  120. data/spec/test_app/app/controllers/sample_namespace/baz_controller.rb +0 -23
  121. data/spec/test_app/app/views/layouts/application.html.erb +0 -12
  122. data/spec/test_app/config/routes.rb +0 -33
  123. data/spec/test_app/spec/generator_helper.rb +0 -87
  124. data/spec/test_app/spec/generators/paloma_generator_spec.rb +0 -199
  125. data/spec/test_app/spec/generators/rails_generator_spec.rb +0 -54
  126. data/spec/test_app/spec/javascripts/callback_spec.rb +0 -64
  127. data/spec/test_app/spec/javascripts/filters_spec.rb +0 -187
  128. data/spec/test_app/spec/javascripts/locals_spec.rb +0 -27
  129. data/spec/test_app/spec/javascripts/params_spec.rb +0 -116
  130. data/spec/test_app/spec/javascripts/skip_filters_spec.rb +0 -58
  131. data/spec/test_app/spec/javascripts/variable_container_spec.rb +0 -21
  132. data/vendor/assets/javascripts/paloma_core.js +0 -296
@@ -1,187 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Paloma.FilterScope', :type => :feature, :js => true do
4
-
5
- shared_context 'paths-' do
6
- let(:basic_action) { basic_action_bar_path }
7
- let(:another_basic_action) { another_basic_action_bar_path }
8
- let(:yet_another_basic_action) { yet_another_basic_action_bar_path}
9
- end
10
-
11
- shared_context 'paths-Application' do
12
- include_context 'paths-'
13
- end
14
-
15
- shared_context 'paths-Namespaced' do
16
- let(:basic_action) { basic_action_sample_namespace_baz_path }
17
- let(:another_basic_action) { another_basic_action_sample_namespace_baz_path }
18
- let(:yet_another_basic_action) { yet_another_basic_action_sample_namespace_baz_path }
19
- end
20
-
21
-
22
-
23
- shared_examples 'standard' do |options|
24
- type = options[:type]
25
- name = options[:name]
26
- method = options[:method] || "##{type}"
27
- scope = parse_scope options[:scope]
28
- filter = "#{scope}Standard #{name}"
29
-
30
- describe method do
31
- it "executes filter #{type} callbacks for the passed actions" do
32
- visit basic_action
33
- page.evaluate_script("filtersExecuted.#{type}").should include filter
34
- end
35
-
36
- it "does not execute filter #{type} callbacks for other actions" do
37
- visit yet_another_basic_action
38
- page.evaluate_script("filtersExecuted.#{type}").should_not include filter
39
- end
40
- end
41
- end
42
-
43
-
44
- shared_examples 'all' do |options|
45
- type = options[:type]
46
- name = options[:name]
47
- method = options[:method] || "##{type}_all"
48
- scope = parse_scope options[:scope]
49
- filter = "#{scope}#{name} All"
50
-
51
- describe method do
52
- it "executes filter #{type} callbacks on all actions" do
53
- visit basic_action
54
- page.evaluate_script("filtersExecuted.#{type}").should include filter
55
- end
56
- end
57
- end
58
-
59
-
60
- shared_examples 'except' do |options|
61
- type = options[:type]
62
- name = options[:name]
63
- method = options[:method] || "#except_#{type}"
64
- scope = parse_scope options[:scope]
65
- filter = "#{scope}Except #{name}"
66
-
67
- describe method do
68
- it "executes filter #{type} callback on all actions except for passed actions" do
69
- visit another_basic_action
70
- page.evaluate_script("filtersExecuted.#{type}").should include filter
71
- end
72
-
73
- it "does not execute filter #{type} callback on passed actions" do
74
- visit basic_action
75
- page.evaluate_script("filtersExecuted.#{type}").should_not include filter
76
- end
77
- end
78
- end
79
-
80
-
81
- shared_examples 'filter subtypes' do |options|
82
- params = {:type => options[:type],
83
- :name => options[:type].titleize,
84
- :scope => options[:scope]}
85
-
86
- include_examples 'standard', params
87
- include_examples 'all', params
88
- include_examples 'except', params
89
- end
90
-
91
-
92
- shared_examples 'filters' do |scope|
93
- context "when inside the scope of #{scope}" do
94
- include_context "paths-#{scope}"
95
-
96
- def self.parse_scope scope
97
- scope.blank? ? scope : "#{scope} "
98
- end
99
-
100
- # Before and After Filters
101
- include_examples 'filter subtypes', {:type => 'before', :scope => scope}
102
- include_examples 'filter subtypes', {:type => 'after', :scope => scope}
103
-
104
- # Around Filters
105
- include_examples 'standard', {:name => 'Around',
106
- :type => 'before',
107
- :method => '#around',
108
- :scope => scope}
109
-
110
- include_examples 'standard', {:name => 'Around',
111
- :type => 'after',
112
- :method => '#around',
113
- :scope => scope}
114
-
115
- include_examples 'all', {:name => 'Around',
116
- :type => 'before',
117
- :method => '#around_all',
118
- :scope => scope}
119
-
120
- include_examples 'all', {:name => 'Around',
121
- :type => 'after',
122
- :method => '#around_all',
123
- :scope => scope}
124
-
125
- include_examples 'except', {:name => 'Around',
126
- :type => 'before',
127
- :method => '#except_around',
128
- :scope => scope}
129
-
130
- include_examples 'except', {:name => 'Around',
131
- :type => 'after',
132
- :method => '#except_around',
133
- :scope => scope}
134
- end
135
- end
136
-
137
-
138
-
139
- shared_examples 'skip filters' do |type|
140
- name = type.titleize
141
- filter = "- Skip This #{name} Filter"
142
-
143
- describe "#skip_#{type}_filter" do
144
- context 'when not appended with #only or #expect' do
145
- it "skips passed #{type} filters for all actions" do
146
- visit basic_action_sample_namespace_baz_path
147
- page.evaluate_script("filtersExecuted.#{type}").should_not include "All #{filter}"
148
- end
149
- end
150
-
151
- context 'with #only' do
152
- it "skips passed #{type} filters for actions passed on #only" do
153
- visit another_basic_action_sample_namespace_baz_path
154
- page.evaluate_script("filtersExecuted.#{type}").should_not include "Only #{filter}"
155
- end
156
-
157
- it "performs passed #{type} filters for actions not passed on #only" do
158
- visit basic_action_sample_namespace_baz_path
159
- page.evaluate_script("filtersExecuted.#{type}").should include "Only #{filter}"
160
- end
161
- end
162
-
163
- context 'with #except' do
164
- it "skips passed #{type} filters for actions not passed on #except" do
165
- visit yet_another_basic_action_sample_namespace_baz_path
166
- page.evaluate_script("filtersExecuted.#{type}").should_not include "Except #{filter}"
167
- end
168
-
169
- it "performs passed #{type} filters for actions passed on #except" do
170
- visit another_basic_action_sample_namespace_baz_path
171
- page.evaluate_script("filtersExecuted.#{type}").should include "Except #{filter}"
172
- end
173
- end
174
- end
175
- end
176
-
177
-
178
-
179
- # Testing starts here
180
- include_examples 'filters', '' # non-namespaced filters
181
- include_examples 'filters', 'Namespaced' # namespaced filters
182
- include_examples 'filters', 'Application' # application-wide filters
183
-
184
- #include_examples 'skip filters', 'before'
185
- #include_examples 'skip filters', 'after'
186
- #include_examples 'skip filters', 'around'
187
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- describe 'Locals', :type => :feature, :js => true do
5
-
6
- before do
7
- visit basic_action_foo_path
8
- end
9
-
10
-
11
- describe '_l' do
12
- it 'has access to local methods' do
13
- page.evaluate_script('helperMethodValue').should be 100
14
- end
15
-
16
-
17
- it 'has access to local variables' do
18
- page.evaluate_script('helperVariableValue').should be 99
19
- end
20
-
21
-
22
- it 'can override locals from its parent scope' do
23
- page.evaluate_script('overriden').should eq 'Override!'
24
- end
25
- end
26
-
27
- end
@@ -1,116 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Callback params', :type => :feature, :js => true do
4
-
5
- shared_examples 'check params' do |params|
6
- specify "callback_controller must be the callback's controller" do
7
- page.evaluate_script('params.callback_controller').should eq params[:callback_controller]
8
- end
9
-
10
- specify "callback_action must be the callback's action" do
11
- page.evaluate_script('params.callback_action').should eq params[:callback_action]
12
- end
13
-
14
- specify "callback_namespace must be callback's namespace" do
15
- page.evaluate_script('params.callback_namespace').should eq params[:callback_namespace]
16
- end
17
-
18
- specify "callback_controller_path must be callback's namespace and controller" do
19
- page.evaluate_script('params.callback_controller_path').should eq params[:callback_controller_path]
20
- end
21
-
22
- specify "controller must be request's controller" do
23
- page.evaluate_script('params.controller').should eq params[:controller]
24
- end
25
-
26
- specify "action must be request's action" do
27
- page.evaluate_script('params.action').should eq params[:action]
28
- end
29
-
30
- specify "namespace must be request's namespace" do
31
- page.evaluate_script('params.namespace').should eq params[:namespace]
32
- end
33
-
34
- specify "controller_path must be request's namespace and controller" do
35
- page.evaluate_script('params.controller_path').should eq params[:controller_path]
36
- end
37
- end
38
-
39
-
40
- context 'within a non-namespaced callback' do
41
- before do
42
- visit callback_from_another_action_foo_path
43
- end
44
-
45
- include_examples('check params', {
46
- :controller => 'foo',
47
- :action => 'callback_from_another_action',
48
- :namespace => '',
49
- :controller_path => 'foo',
50
- :callback_controller => 'foo',
51
- :callback_action => 'basic_action',
52
- :callback_namespace => '',
53
- :callback_controller_path => 'foo'})
54
- end
55
-
56
-
57
- context 'within a namespaced callback' do
58
- before do
59
- visit callback_from_another_action_sample_namespace_baz_path
60
- end
61
-
62
- include_examples('check params', {
63
- :controller => 'baz',
64
- :action => 'callback_from_another_action',
65
- :namespace => 'sample_namespace',
66
- :controller_path => 'sample_namespace/baz',
67
- :callback_controller => 'baz',
68
- :callback_action => 'basic_action',
69
- :callback_namespace => 'sample_namespace',
70
- :callback_controller_path => 'sample_namespace/baz'})
71
- end
72
-
73
-
74
- context 'with passed parameter' do
75
- before do
76
- visit different_params_bar_path
77
- end
78
-
79
- context 'of type TrueClass or FalseClass' do
80
- it 'has the boolean equivalent' do
81
- page.evaluate_script("params['boolean'] == true").should be_true
82
- end
83
- end
84
-
85
- context 'of type Array' do
86
- it 'has the array equivalent' do
87
- page.evaluate_script("JSON.stringify(params['array']) == JSON.stringify([1, 2, 3])").should be_true
88
- end
89
- end
90
-
91
- context 'of type String' do
92
- it 'has the string equivalent' do
93
- page.evaluate_script("params['string'] == 'Banana'").should be_true
94
- end
95
- end
96
-
97
- context 'of type Fixnum' do
98
- it 'has the number equivalent' do
99
- page.evaluate_script("params['integer'] == 69").should be_true
100
- end
101
- end
102
-
103
- context 'of type Float' do
104
- it 'has the number equivalent' do
105
- page.evaluate_script("params['float'] == 3.1416").should be_true
106
- end
107
- end
108
-
109
- context 'of type Hash' do
110
- it 'has the object equivalent' do
111
- page.evaluate_script(
112
- "JSON.stringify(params['hash']) == JSON.stringify({a : 'Hello', b : 'World'})").should be_true
113
- end
114
- end
115
- end
116
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- describe 'Skip Filter', :type => :feature, :js => true do
5
-
6
- def filters_executed type
7
- page.evaluate_script("filtersExecuted.#{type}")
8
- end
9
-
10
-
11
- shared_examples 'skip_*_filter/s' do |execution, name|
12
-
13
- describe "#skip_#{name}_filter/s" do
14
- context "with no inclusion method called" do
15
- it "skips the #{name} filters" do
16
- visit basic_action_bar_path
17
- filters_executed(execution).should_not include "Standard Skip #{name.titleize} Filter"
18
- end
19
- end
20
-
21
-
22
- context "with #only inclusion method called" do
23
- filter = "Only Skip #{name.titleize} Filter"
24
-
25
- it "skips the #{name} filters for the actions passed" do
26
- visit basic_action_bar_path
27
- filters_executed(execution).should_not include filter
28
- end
29
-
30
- it "does not skip the #{name} filters for the other actions" do
31
- visit another_basic_action_bar_path
32
- filters_executed(execution).should include filter
33
- end
34
- end
35
-
36
-
37
- context "with #except inclusion method called" do
38
- filter = "Except Skip #{name.titleize} Filter"
39
-
40
- it "skips the #{name} filters for the actions which are not passed" do
41
- visit basic_action_bar_path
42
- filters_executed(execution).should_not include filter
43
- end
44
-
45
- it "does not skip the #{name} filters for the actions passed" do
46
- visit yet_another_basic_action_bar_path
47
- filters_executed(execution).should include filter
48
- end
49
- end
50
- end
51
- end
52
-
53
-
54
- include_examples 'skip_*_filter/s', 'before', 'before'
55
- include_examples 'skip_*_filter/s', 'after', 'after'
56
- include_examples 'skip_*_filter/s', 'before', 'around'
57
- include_examples 'skip_*_filter/s', 'after', 'around'
58
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- describe '_x', :type => :feature, :js => true do
5
-
6
- before do
7
- visit basic_action_foo_path
8
- end
9
-
10
-
11
- it 'is visible on filters and callback' do
12
- final_x = page.evaluate_script 'window.xVisibilityFinal'
13
- final_x.should eq ['Before Foo', 'Around Foo', 'Foo', 'After Foo', 'Around Foo']
14
- end
15
-
16
-
17
- it 'is empty after filter and callback executions' do
18
- x = page.evaluate_script 'Paloma.variableContainer'
19
- x.should be_empty
20
- end
21
- end
@@ -1,296 +0,0 @@
1
- (function(){
2
- window.Paloma = {
3
- callbacks : {},
4
- filterScopes : {},
5
- locals : {},
6
- variableContainer : {}
7
- };
8
-
9
-
10
- var FILTER_TYPES = {},
11
- FILTER_TYPE_NAMES = ['BEFORE', 'AFTER', 'AROUND'],
12
- INCLUSION_TYPES = {},
13
- INCLUSION_TYPE_NAMES = ['ALL', 'ONLY', 'EXCEPT'];
14
-
15
- FILTER_TYPES.BEFORE = 0;
16
- FILTER_TYPES.AFTER = 1;
17
- FILTER_TYPES.AROUND = 2;
18
-
19
- INCLUSION_TYPES.ALL = 3;
20
- INCLUSION_TYPES.ONLY = 4;
21
- INCLUSION_TYPES.EXCEPT = 5;
22
-
23
-
24
- Paloma.inheritLocals = function(options){
25
- var from = Paloma.locals[options['from']],
26
- to = Paloma.locals[options['to']];
27
-
28
- for (var local in from){
29
- // Overriding is allowed.
30
- if ( to.hasOwnProperty(local) ){ continue; }
31
-
32
- to[local] = from[local];
33
- }
34
- };
35
-
36
-
37
-
38
- Paloma.FilterScope = function(name){
39
- this.name = name;
40
-
41
- this.filters = {};
42
- this.skippers = {};
43
-
44
- for (var i = 0, n = FILTER_TYPE_NAMES.length; i < n; i++){
45
- var type = FILTER_TYPE_NAMES[i].toUpperCase();
46
- this.filters[ FILTER_TYPES[type] ] = [];
47
- this.skippers[ FILTER_TYPES[type] ] = [];
48
- }
49
-
50
- Paloma.filterScopes[name] = this;
51
- };
52
-
53
-
54
- // Creates a new Filter instance registered under this FilterScope.
55
- Paloma.FilterScope.prototype.as = function(filterName){
56
- return (new Paloma.Filter(this, filterName));
57
- };
58
-
59
-
60
- // skip_*_filter/s methods
61
- (function(){
62
- for (var i = 0, n = FILTER_TYPE_NAMES.length; i < n; i++){
63
- var type = FILTER_TYPE_NAMES[i],
64
- singular = 'skip_' + type.toLowerCase() + '_filter',
65
- plural = singular + 's',
66
- method = function(skipperType){
67
- return function(){
68
- return (new Paloma.Skipper(this, FILTER_TYPES[skipperType], arguments));
69
- };
70
- };
71
-
72
- Paloma.FilterScope.prototype[singular] = new method(type);
73
- Paloma.FilterScope.prototype[plural] = Paloma.FilterScope.prototype[singular];
74
- }
75
- })();
76
-
77
-
78
-
79
-
80
- // Skipper class
81
- Paloma.Skipper = function(scope, type, filters){
82
- this.scope = scope;
83
- this.type = type;
84
- this.filters = Array.prototype.slice.call(filters);
85
- this.inclusionType = INCLUSION_TYPES.ALL;
86
- this.actions = [];
87
-
88
- // Register this skipper on its scope.
89
- this.scope.skippers[this.type].push(this);
90
- };
91
-
92
-
93
- Paloma.Skipper.prototype.skip = function(filter, action){
94
- if (this.filters.indexOf(filter.name) == -1){ return false; }
95
-
96
- var actionIsListed = this.actions.indexOf(action) != -1,
97
- isAllActions = this.inclusionType == INCLUSION_TYPES.ALL,
98
- isQualified = this.inclusionType == INCLUSION_TYPES.ONLY && actionIsListed,
99
- isNotExcepted = this.inclusionType == INCLUSION_TYPES.EXCEPT && !actionIsListed;
100
-
101
- return (isAllActions || isQualified || isNotExcepted);
102
- };
103
-
104
-
105
- Paloma.Skipper.prototype.only = function(){
106
- this.inclusionType = INCLUSION_TYPES.ONLY;
107
- this.actions = Array.prototype.slice.call(arguments);
108
- };
109
-
110
-
111
- Paloma.Skipper.prototype.except = function(){
112
- this.inclusionType = INCLUSION_TYPES.EXCEPT;
113
- this.actions = Array.prototype.slice.call(arguments);
114
- };
115
-
116
-
117
-
118
- // Filter class
119
- Paloma.Filter = function(scope, name){
120
- this.scope = scope;
121
- this.name = name;
122
-
123
- this.type = undefined;
124
- this.inclusionType = INCLUSION_TYPES.ONLY;
125
-
126
- this.actions = [];
127
- this.method = undefined;
128
- };
129
-
130
-
131
- // Create Methods:
132
- // - before, after, around, *_all, except_*
133
- (function(){
134
- var Basic = function(type){
135
- return function(){
136
- return this.setProperties(type, INCLUSION_TYPES.ONLY, arguments);
137
- };
138
- };
139
-
140
- var All = function(type){
141
- return function(){
142
- return this.setProperties(type, INCLUSION_TYPES.ALL, []);
143
- };
144
- };
145
-
146
- var Except = function(type){
147
- return function(){
148
- return this.setProperties(type, INCLUSION_TYPES.EXCEPT, arguments);
149
- };
150
- };
151
-
152
- for (var i = 0, n = FILTER_TYPE_NAMES.length; i < n; i++){
153
- var name = FILTER_TYPE_NAMES[i].toLowerCase(),
154
- type = FILTER_TYPES[name.toUpperCase()];
155
-
156
- Paloma.Filter.prototype[name] = new Basic(type);
157
- Paloma.Filter.prototype[name + '_all'] = new All(type);
158
- Paloma.Filter.prototype['except_' + name] = new Except(type);
159
- }
160
- })();
161
- // End of creating methods.
162
-
163
-
164
- // This will be the last method to be invoked when declaring a filter.
165
- // This will set what method/function will be executed when the filter is called.
166
- Paloma.Filter.prototype.perform = function(method){
167
- this.method = method;
168
-
169
- // This is the only time the filter is registered to its owner scope.
170
- this.scope.filters[this.type].push(this);
171
- return this;
172
- };
173
-
174
-
175
- Paloma.Filter.prototype.isApplicable = function(action){
176
- var actionIsListed = this.actions.indexOf(action) != -1,
177
- isAllActions = this.inclusionType == INCLUSION_TYPES.ALL,
178
- isQualified = this.inclusionType == INCLUSION_TYPES.ONLY && actionIsListed,
179
- isNotExcepted = this.inclusionType == INCLUSION_TYPES.EXCEPT && !actionIsListed;
180
-
181
- return (isAllActions || isQualified || isNotExcepted);
182
- };
183
-
184
-
185
- Paloma.Filter.prototype.setProperties = function(type, inclusion, actions){
186
- this.type = type;
187
- this.inclusionType = inclusion;
188
- this.actions = Array.prototype.slice.call(actions);
189
- return this;
190
- };
191
-
192
-
193
-
194
-
195
- // Execute callback that corresponds to the controller and action passed.
196
- Paloma.execute = function(controller, action, params){
197
- var callbackFound = true;
198
-
199
- var callback = Paloma.callbacks[controller];
200
- callbackFound = callback != undefined;
201
-
202
- if (callbackFound){
203
- callback = callback[action];
204
- callbackFound = callback != undefined;
205
- }
206
-
207
- // Parse parameters
208
- params = params || {};
209
-
210
- // Request details
211
- var requestControllerPath = params['controller_path'].split('/');
212
- params['controller'] = requestControllerPath.pop();
213
- params['namespace'] = requestControllerPath.join('/');
214
-
215
- // Callback details
216
- var callbackControllerPath = controller.split('/');
217
- params['callback_controller'] = callbackControllerPath.pop();
218
- params['callback_namespace'] = callbackControllerPath.join('/');
219
- params['callback_controller_path'] = controller;
220
- params['callback_action'] = action;
221
-
222
-
223
- var beforeFilters = getOrderedFilters(
224
- FILTER_TYPES.BEFORE,
225
- params['callback_namespace'],
226
- controller,
227
- action);
228
-
229
- var afterFilters = getOrderedFilters(
230
- FILTER_TYPES.AFTER,
231
- params['callback_namespace'],
232
- controller,
233
- action);
234
-
235
- // Start filter and callback executions
236
- performFilters(beforeFilters, params);
237
- if (callbackFound){ callback(params); }
238
- performFilters(afterFilters, params);
239
-
240
- // variableContainer is used to share variable between filters and callbacks.
241
- // It will be cleared after it is used.
242
- Paloma.variableContainer = [];
243
- };
244
-
245
-
246
- var getOrderedFilters = function(beforeOrAfter, namespace, controller, action){
247
- var filters = [],
248
- applicableFilters = [],
249
- skippers = [],
250
- scopes = [
251
- Paloma.filterScopes['/'],
252
- Paloma.filterScopes[namespace],
253
- Paloma.filterScopes[controller]];
254
-
255
- for (var i = 0, n = scopes.length; i < n; i++){
256
- var scope = scopes[i];
257
- if (scope == undefined){ continue; }
258
-
259
- var mainFilters = scope.filters[beforeOrAfter],
260
- aroundFilters = scope.filters[FILTER_TYPES.AROUND];
261
-
262
- // Around Filters have lower precedence than before or after filters.
263
- if (mainFilters != undefined){ filters = filters.concat(mainFilters); }
264
- if (aroundFilters != undefined){ filters = filters.concat(aroundFilters); }
265
-
266
- skippers = skippers.concat(
267
- scope.skippers[beforeOrAfter],
268
- scope.skippers[FILTER_TYPES.AROUND]);
269
- }
270
-
271
-
272
- // Select only applicable filters for the passed action.
273
- for (var i = 0, n = filters.length; i < n; i++){
274
- var filter = filters[i],
275
- isApplicable = filter.isApplicable(action),
276
- isNotSkipped = true;
277
-
278
- for (var k = 0, len = skippers.length; k < len; k++){
279
- if ( skippers[k].skip(filter, action) ){ isNotSkipped = false; break;}
280
- }
281
-
282
- if (isApplicable && isNotSkipped){ applicableFilters.push(filter); }
283
- }
284
-
285
- return applicableFilters;
286
- };
287
-
288
-
289
- var performFilters = function(filters, params){
290
- for (var i = 0, n = filters.length; i < n; i++){
291
- filters[i].method(params);
292
- }
293
- };
294
-
295
-
296
- })();