object-filters 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /pkg
2
+ .rvmrc
3
+ .DS_Store
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'bundler'
7
+ gem 'rspec'
8
+ end
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rake/version_task'
2
+ require 'rspec/core/rake_task'
3
+
4
+ spec = Gem::Specification.new do |s|
5
+ s.name = 'object-filters'
6
+ s.platform = Gem::Platform::RUBY
7
+ s.author = 'Ryan Scott Lewis'
8
+ s.email = 'ryan@rynet.us'
9
+ s.homepage = "http://rubygems.org/gems/#{s.name}"
10
+ s.summary = 'Use before, after, and around filters with your objects!'
11
+ s.description = 'This gem provides ActionController::Filters for your custom classes.'
12
+ s.require_path = 'lib'
13
+ s.post_install_message = "This is a placeholder gem... for now. Check back in a few versions!"
14
+ s.files = `git ls-files`.lines.to_a.collect { |s| s.strip }
15
+ s.executables = `git ls-files -- bin/*`.lines.to_a.collect { |s| File.basename(s.strip) }
16
+
17
+ s.add_dependency 'version', '~> 1'
18
+ s.add_dependency 'active_support', '~> 3'
19
+ end
20
+
21
+ Rake::VersionTask.new do |t|
22
+ t.with_git_tag = true
23
+ t.with_gemspec = spec
24
+ end
25
+
26
+ RSpec::Core::RakeTask.new
27
+
28
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.5
data/filters.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "object-filters"
5
+ s.version = "0.0.5"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ryan Scott Lewis"]
9
+ s.date = "2012-10-08"
10
+ s.description = "This gem provides ActionController::Filters for normal applications."
11
+ s.email = ["ryan@rynet.us"]
12
+ s.files = [".gitignore", "Gemfile", "Rakefile", "VERSION", "filters.gemspec", "lib/filters.rb", "spec/filters_spec.rb", "spec/spec_helper.rb"]
13
+ s.homepage = "http://rubygems.org/gems/filters"
14
+ s.post_install_message = "This is a placeholder gem... for now. Check back in a few versions!"
15
+ s.require_paths = ["lib"]
16
+ s.rubygems_version = "1.8.24"
17
+ s.summary = "Use before, after, and around filters with your objects!"
18
+
19
+ if s.respond_to? :specification_version then
20
+ s.specification_version = 3
21
+
22
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
+ s.add_runtime_dependency(%q<version>, ["~> 1"])
24
+ s.add_runtime_dependency(%q<active_support>, ["~> 3"])
25
+ else
26
+ s.add_dependency(%q<version>, ["~> 1"])
27
+ s.add_dependency(%q<active_support>, ["~> 3"])
28
+ end
29
+ else
30
+ s.add_dependency(%q<version>, ["~> 1"])
31
+ s.add_dependency(%q<active_support>, ["~> 3"])
32
+ end
33
+ end
data/lib/filters.rb ADDED
@@ -0,0 +1,203 @@
1
+ require 'pathname'
2
+ require 'bundler/setup'
3
+ require 'version'
4
+ require 'active_support/concern'
5
+ require 'active_support/callbacks'
6
+
7
+ __PATH__ = Pathname.new(__FILE__)
8
+ $:.unshift(__PATH__.dirname.to_s) unless $:.include?(__PATH__.dirname.to_s)
9
+
10
+ module AbstractController
11
+ module Callbacks
12
+ extend ActiveSupport::Concern
13
+
14
+ # Uses ActiveSupport::Callbacks as the base functionality. For
15
+ # more details on the whole callback system, read the documentation
16
+ # for ActiveSupport::Callbacks.
17
+ include ActiveSupport::Callbacks
18
+
19
+ included do
20
+ define_callbacks :process_action, :terminator => "response_body", :skip_after_callbacks_if_terminated => true
21
+ end
22
+
23
+ # Override AbstractController::Base's process_action to run the
24
+ # process_action callbacks around the normal behavior.
25
+ def process_action(*args)
26
+ run_callbacks(:process_action) do
27
+ super
28
+ end
29
+ end
30
+
31
+ module ClassMethods
32
+ # If :only or :except are used, convert the options into the
33
+ # :unless and :if options of ActiveSupport::Callbacks.
34
+ # The basic idea is that :only => :index gets converted to
35
+ # :if => proc {|c| c.action_name == "index" }.
36
+ #
37
+ # ==== Options
38
+ # * <tt>only</tt> - The callback should be run only for this action
39
+ # * <tt>except</tt> - The callback should be run for all actions except this action
40
+ def _normalize_callback_options(options)
41
+ if only = options[:only]
42
+ only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ")
43
+ options[:if] = Array(options[:if]) << only
44
+ end
45
+ if except = options[:except]
46
+ except = Array(except).map {|e| "action_name == '#{e}'"}.join(" || ")
47
+ options[:unless] = Array(options[:unless]) << except
48
+ end
49
+ end
50
+
51
+ # Skip before, after, and around filters matching any of the names
52
+ #
53
+ # ==== Parameters
54
+ # * <tt>names</tt> - A list of valid names that could be used for
55
+ # callbacks. Note that skipping uses Ruby equality, so it's
56
+ # impossible to skip a callback defined using an anonymous proc
57
+ # using #skip_filter
58
+ def skip_filter(*names)
59
+ skip_before_filter(*names)
60
+ skip_after_filter(*names)
61
+ skip_around_filter(*names)
62
+ end
63
+
64
+ # Take callback names and an optional callback proc, normalize them,
65
+ # then call the block with each callback. This allows us to abstract
66
+ # the normalization across several methods that use it.
67
+ #
68
+ # ==== Parameters
69
+ # * <tt>callbacks</tt> - An array of callbacks, with an optional
70
+ # options hash as the last parameter.
71
+ # * <tt>block</tt> - A proc that should be added to the callbacks.
72
+ #
73
+ # ==== Block Parameters
74
+ # * <tt>name</tt> - The callback to be added
75
+ # * <tt>options</tt> - A hash of options to be used when adding the callback
76
+ def _insert_callbacks(callbacks, block = nil)
77
+ options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
78
+ _normalize_callback_options(options)
79
+ callbacks.push(block) if block
80
+ callbacks.each do |callback|
81
+ yield callback, options
82
+ end
83
+ end
84
+
85
+ ##
86
+ # :method: before_filter
87
+ #
88
+ # :call-seq: before_filter(names, block)
89
+ #
90
+ # Append a before filter. See _insert_callbacks for parameter details.
91
+
92
+ ##
93
+ # :method: prepend_before_filter
94
+ #
95
+ # :call-seq: prepend_before_filter(names, block)
96
+ #
97
+ # Prepend a before filter. See _insert_callbacks for parameter details.
98
+
99
+ ##
100
+ # :method: skip_before_filter
101
+ #
102
+ # :call-seq: skip_before_filter(names)
103
+ #
104
+ # Skip a before filter. See _insert_callbacks for parameter details.
105
+
106
+ ##
107
+ # :method: append_before_filter
108
+ #
109
+ # :call-seq: append_before_filter(names, block)
110
+ #
111
+ # Append a before filter. See _insert_callbacks for parameter details.
112
+
113
+ ##
114
+ # :method: after_filter
115
+ #
116
+ # :call-seq: after_filter(names, block)
117
+ #
118
+ # Append an after filter. See _insert_callbacks for parameter details.
119
+
120
+ ##
121
+ # :method: prepend_after_filter
122
+ #
123
+ # :call-seq: prepend_after_filter(names, block)
124
+ #
125
+ # Prepend an after filter. See _insert_callbacks for parameter details.
126
+
127
+ ##
128
+ # :method: skip_after_filter
129
+ #
130
+ # :call-seq: skip_after_filter(names)
131
+ #
132
+ # Skip an after filter. See _insert_callbacks for parameter details.
133
+
134
+ ##
135
+ # :method: append_after_filter
136
+ #
137
+ # :call-seq: append_after_filter(names, block)
138
+ #
139
+ # Append an after filter. See _insert_callbacks for parameter details.
140
+
141
+ ##
142
+ # :method: around_filter
143
+ #
144
+ # :call-seq: around_filter(names, block)
145
+ #
146
+ # Append an around filter. See _insert_callbacks for parameter details.
147
+
148
+ ##
149
+ # :method: prepend_around_filter
150
+ #
151
+ # :call-seq: prepend_around_filter(names, block)
152
+ #
153
+ # Prepend an around filter. See _insert_callbacks for parameter details.
154
+
155
+ ##
156
+ # :method: skip_around_filter
157
+ #
158
+ # :call-seq: skip_around_filter(names)
159
+ #
160
+ # Skip an around filter. See _insert_callbacks for parameter details.
161
+
162
+ ##
163
+ # :method: append_around_filter
164
+ #
165
+ # :call-seq: append_around_filter(names, block)
166
+ #
167
+ # Append an around filter. See _insert_callbacks for parameter details.
168
+
169
+ # set up before_filter, prepend_before_filter, skip_before_filter, etc.
170
+ # for each of before, after, and around.
171
+ [:before, :after, :around].each do |filter|
172
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
173
+ # Append a before, after or around filter. See _insert_callbacks
174
+ # for details on the allowed parameters.
175
+ def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
176
+ _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
177
+ set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before, name, options)
178
+ end # end
179
+ end # end
180
+
181
+ # Prepend a before, after or around filter. See _insert_callbacks
182
+ # for details on the allowed parameters.
183
+ def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
184
+ _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
185
+ set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
186
+ end # end
187
+ end # end
188
+
189
+ # Skip a before, after or around filter. See _insert_callbacks
190
+ # for details on the allowed parameters.
191
+ def skip_#{filter}_filter(*names) # def skip_before_filter(*names)
192
+ _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options|
193
+ skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options)
194
+ end # end
195
+ end # end
196
+
197
+ # *_filter is the same as append_*_filter
198
+ alias_method :append_#{filter}_filter, :#{filter}_filter # alias_method :append_before_filter, :before_filter
199
+ RUBY_EVAL
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,298 @@
1
+ require 'spec_helper'
2
+
3
+ __END__
4
+
5
+ module AbstractController
6
+ module Testing
7
+
8
+ class ControllerWithCallbacks < AbstractController::Base
9
+ include AbstractController::Callbacks
10
+ end
11
+
12
+ class Callback1 < ControllerWithCallbacks
13
+ set_callback :process_action, :before, :first
14
+
15
+ def first
16
+ @text = "Hello world"
17
+ end
18
+
19
+ def index
20
+ self.response_body = @text
21
+ end
22
+ end
23
+
24
+ class TestCallbacks1 < ActiveSupport::TestCase
25
+ test "basic callbacks work" do
26
+ controller = Callback1.new
27
+ controller.process(:index)
28
+ assert_equal "Hello world", controller.response_body
29
+ end
30
+ end
31
+
32
+ class Callback2 < ControllerWithCallbacks
33
+ before_filter :first
34
+ after_filter :second
35
+ around_filter :aroundz
36
+
37
+ def first
38
+ @text = "Hello world"
39
+ end
40
+
41
+ def second
42
+ @second = "Goodbye"
43
+ end
44
+
45
+ def aroundz
46
+ @aroundz = "FIRST"
47
+ yield
48
+ @aroundz << "SECOND"
49
+ end
50
+
51
+ def index
52
+ @text ||= nil
53
+ self.response_body = @text.to_s
54
+ end
55
+ end
56
+
57
+ class Callback2Overwrite < Callback2
58
+ before_filter :first, :except => :index
59
+ end
60
+
61
+ class TestCallbacks2 < ActiveSupport::TestCase
62
+ def setup
63
+ @controller = Callback2.new
64
+ end
65
+
66
+ test "before_filter works" do
67
+ @controller.process(:index)
68
+ assert_equal "Hello world", @controller.response_body
69
+ end
70
+
71
+ test "after_filter works" do
72
+ @controller.process(:index)
73
+ assert_equal "Goodbye", @controller.instance_variable_get("@second")
74
+ end
75
+
76
+ test "around_filter works" do
77
+ @controller.process(:index)
78
+ assert_equal "FIRSTSECOND", @controller.instance_variable_get("@aroundz")
79
+ end
80
+
81
+ test "before_filter with overwritten condition" do
82
+ @controller = Callback2Overwrite.new
83
+ @controller.process(:index)
84
+ assert_equal "", @controller.response_body
85
+ end
86
+ end
87
+
88
+ class Callback3 < ControllerWithCallbacks
89
+ before_filter do |c|
90
+ c.instance_variable_set("@text", "Hello world")
91
+ end
92
+
93
+ after_filter do |c|
94
+ c.instance_variable_set("@second", "Goodbye")
95
+ end
96
+
97
+ def index
98
+ self.response_body = @text
99
+ end
100
+ end
101
+
102
+ class TestCallbacks3 < ActiveSupport::TestCase
103
+ def setup
104
+ @controller = Callback3.new
105
+ end
106
+
107
+ test "before_filter works with procs" do
108
+ @controller.process(:index)
109
+ assert_equal "Hello world", @controller.response_body
110
+ end
111
+
112
+ test "after_filter works with procs" do
113
+ @controller.process(:index)
114
+ assert_equal "Goodbye", @controller.instance_variable_get("@second")
115
+ end
116
+ end
117
+
118
+ class CallbacksWithConditions < ControllerWithCallbacks
119
+ before_filter :list, :only => :index
120
+ before_filter :authenticate, :except => :index
121
+
122
+ def index
123
+ self.response_body = @list.join(", ")
124
+ end
125
+
126
+ def sekrit_data
127
+ self.response_body = (@list + [@authenticated]).join(", ")
128
+ end
129
+
130
+ private
131
+ def list
132
+ @list = ["Hello", "World"]
133
+ end
134
+
135
+ def authenticate
136
+ @list ||= []
137
+ @authenticated = "true"
138
+ end
139
+ end
140
+
141
+ class TestCallbacksWithConditions < ActiveSupport::TestCase
142
+ def setup
143
+ @controller = CallbacksWithConditions.new
144
+ end
145
+
146
+ test "when :only is specified, a before filter is triggered on that action" do
147
+ @controller.process(:index)
148
+ assert_equal "Hello, World", @controller.response_body
149
+ end
150
+
151
+ test "when :only is specified, a before filter is not triggered on other actions" do
152
+ @controller.process(:sekrit_data)
153
+ assert_equal "true", @controller.response_body
154
+ end
155
+
156
+ test "when :except is specified, an after filter is not triggered on that action" do
157
+ @controller.process(:index)
158
+ assert !@controller.instance_variable_defined?("@authenticated")
159
+ end
160
+ end
161
+
162
+ class CallbacksWithArrayConditions < ControllerWithCallbacks
163
+ before_filter :list, :only => [:index, :listy]
164
+ before_filter :authenticate, :except => [:index, :listy]
165
+
166
+ def index
167
+ self.response_body = @list.join(", ")
168
+ end
169
+
170
+ def sekrit_data
171
+ self.response_body = (@list + [@authenticated]).join(", ")
172
+ end
173
+
174
+ private
175
+ def list
176
+ @list = ["Hello", "World"]
177
+ end
178
+
179
+ def authenticate
180
+ @list = []
181
+ @authenticated = "true"
182
+ end
183
+ end
184
+
185
+ class TestCallbacksWithArrayConditions < ActiveSupport::TestCase
186
+ def setup
187
+ @controller = CallbacksWithArrayConditions.new
188
+ end
189
+
190
+ test "when :only is specified with an array, a before filter is triggered on that action" do
191
+ @controller.process(:index)
192
+ assert_equal "Hello, World", @controller.response_body
193
+ end
194
+
195
+ test "when :only is specified with an array, a before filter is not triggered on other actions" do
196
+ @controller.process(:sekrit_data)
197
+ assert_equal "true", @controller.response_body
198
+ end
199
+
200
+ test "when :except is specified with an array, an after filter is not triggered on that action" do
201
+ @controller.process(:index)
202
+ assert !@controller.instance_variable_defined?("@authenticated")
203
+ end
204
+ end
205
+
206
+ class ChangedConditions < Callback2
207
+ before_filter :first, :only => :index
208
+
209
+ def not_index
210
+ @text ||= nil
211
+ self.response_body = @text.to_s
212
+ end
213
+ end
214
+
215
+ class TestCallbacksWithChangedConditions < ActiveSupport::TestCase
216
+ def setup
217
+ @controller = ChangedConditions.new
218
+ end
219
+
220
+ test "when a callback is modified in a child with :only, it works for the :only action" do
221
+ @controller.process(:index)
222
+ assert_equal "Hello world", @controller.response_body
223
+ end
224
+
225
+ test "when a callback is modified in a child with :only, it does not work for other actions" do
226
+ @controller.process(:not_index)
227
+ assert_equal "", @controller.response_body
228
+ end
229
+ end
230
+
231
+ class SetsResponseBody < ControllerWithCallbacks
232
+ before_filter :set_body
233
+
234
+ def index
235
+ self.response_body = "Fail"
236
+ end
237
+
238
+ def set_body
239
+ self.response_body = "Success"
240
+ end
241
+ end
242
+
243
+ class TestHalting < ActiveSupport::TestCase
244
+ test "when a callback sets the response body, the action should not be invoked" do
245
+ controller = SetsResponseBody.new
246
+ controller.process(:index)
247
+ assert_equal "Success", controller.response_body
248
+ end
249
+ end
250
+
251
+ class CallbacksWithArgs < ControllerWithCallbacks
252
+ set_callback :process_action, :before, :first
253
+
254
+ def first
255
+ @text = "Hello world"
256
+ end
257
+
258
+ def index(text)
259
+ self.response_body = @text + text
260
+ end
261
+ end
262
+
263
+ class TestCallbacksWithArgs < ActiveSupport::TestCase
264
+ test "callbacks still work when invoking process with multiple args" do
265
+ controller = CallbacksWithArgs.new
266
+ controller.process(:index, " Howdy!")
267
+ assert_equal "Hello world Howdy!", controller.response_body
268
+ end
269
+ end
270
+
271
+
272
+ end
273
+ end
274
+
275
+ __END__
276
+ describe Filters do
277
+
278
+ let(:dummy_class) { Class.new { include(Filters) } }
279
+
280
+ describe 'ClassMethods' do
281
+ subject { dummy_class }
282
+
283
+ describe '.some_class_method' do
284
+ it { should respond_to(:some_class_method) }
285
+ end
286
+
287
+ end
288
+
289
+ describe 'InstanceMethods' do
290
+ subject { dummy_class.new }
291
+
292
+ describe '#some_instance_method' do
293
+ it { should respond_to(:some_instance_method) }
294
+ end
295
+
296
+ end
297
+
298
+ end
@@ -0,0 +1 @@
1
+ require 'filters'
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: object-filters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Scott Lewis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: version
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: active_support
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3'
46
+ description: This gem provides ActionController::Filters for normal applications.
47
+ email:
48
+ - ryan@rynet.us
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Rakefile
56
+ - VERSION
57
+ - filters.gemspec
58
+ - lib/filters.rb
59
+ - spec/filters_spec.rb
60
+ - spec/spec_helper.rb
61
+ homepage: http://rubygems.org/gems/filters
62
+ licenses: []
63
+ post_install_message: This is a placeholder gem... for now. Check back in a few versions!
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.24
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Use before, after, and around filters with your objects!
85
+ test_files: []