filter_object 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/README.md +106 -0
- data/Rakefile +1 -0
- data/filter_object.gemspec +23 -0
- data/lib/filter_object.rb +16 -0
- data/lib/filter_object/version.rb +3 -0
- data/spec/filter_object_spec.rb +150 -0
- data/spec/spec_helper.rb +7 -0
- metadata +70 -0
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
## TL;DR
|
2
|
+
``` ruby
|
3
|
+
class YourController < ApplicationController
|
4
|
+
before_filter YourFilterClass.new
|
5
|
+
end
|
6
|
+
|
7
|
+
# Inside app/filters/your_filter_class.rb
|
8
|
+
class YourFilterClass
|
9
|
+
include FilterObject::Filter
|
10
|
+
|
11
|
+
def filter(controller)
|
12
|
+
super
|
13
|
+
# your filter logic starts here...
|
14
|
+
end
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
## What's a Filter Object?
|
19
|
+
|
20
|
+
A filter object is a nice way to remove logic from your controller. Usually you start implementing simple filter methods, like these
|
21
|
+
|
22
|
+
``` ruby
|
23
|
+
class YourController < ApplicationController
|
24
|
+
before_filter :your_filter_method
|
25
|
+
|
26
|
+
# your actions...
|
27
|
+
|
28
|
+
private
|
29
|
+
def your_filter_method
|
30
|
+
# some simple logic here...
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
and everything is fine. As the time passes you start to add more code to the `your_filter_method` filter method. It will look like shit after some time...
|
36
|
+
|
37
|
+
Sometimes the problem already starts too complicated for a single method.
|
38
|
+
|
39
|
+
Rails already provides a way to fix this kind of problem. You can do something like this:
|
40
|
+
|
41
|
+
``` ruby
|
42
|
+
class YourController < ApplicationController
|
43
|
+
before_filter FilterClass
|
44
|
+
|
45
|
+
# your actions...
|
46
|
+
end
|
47
|
+
|
48
|
+
class FilterClass
|
49
|
+
def self.filter(controller)
|
50
|
+
# your complex filter logic goes here...
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
and it will work. Only that now you are creating a lot of class methods, which are hard to test. Also, it's hard to keep state inside your filter. The nice thing is that you can easily pass anything that responds to `filter` to the before_filter and after_filter calls. So why not pass an instance?
|
56
|
+
|
57
|
+
``` ruby
|
58
|
+
class YourController < ApplicationController
|
59
|
+
before_filter FilterClass.new
|
60
|
+
|
61
|
+
# your actions...
|
62
|
+
end
|
63
|
+
|
64
|
+
class FilterClass
|
65
|
+
def filter(controller)
|
66
|
+
# your complex filter logic goes here...
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
Ok, now this is real OO! It will much easier to write your tests, too. But you'll need to handle methods delegation to the controller, things like calling `params`, `render`, and so on.
|
72
|
+
|
73
|
+
This is where filter_object comes in.
|
74
|
+
|
75
|
+
``` ruby
|
76
|
+
class FilterClass
|
77
|
+
include FilterObject::Filter
|
78
|
+
|
79
|
+
def filter(controller)
|
80
|
+
super # so filter_object can set the delegations
|
81
|
+
|
82
|
+
if params[:programming_is] != "cool" # the call to params will be automatically redirected to the controller
|
83
|
+
redirect_to program_more_path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
Now you can call controller methods directly inside your filter objects and they will be properly delegated to the controller.
|
90
|
+
|
91
|
+
#### Methods that will be automatically delegated to the controller
|
92
|
+
* params
|
93
|
+
* flash
|
94
|
+
* render
|
95
|
+
* redirect_to
|
96
|
+
* cookies
|
97
|
+
* session
|
98
|
+
* headers
|
99
|
+
* request
|
100
|
+
|
101
|
+
If you are using a controller method that is not listed here, please send a pull request!
|
102
|
+
|
103
|
+
## Why a gem for such a simple and stupid code?
|
104
|
+
|
105
|
+
Because I was repeating this thing all over my projects, so I got tired.
|
106
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "filter_object/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "filter_object"
|
7
|
+
s.version = FilterObject::VERSION
|
8
|
+
s.authors = ["Cássio Marques"]
|
9
|
+
s.email = ["cassiommc@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Create objects to handle filter logic and clean up your controllers}
|
12
|
+
s.description = %q{You can use filter_object to write classes whose instances encapsulate your filter logic, so you can have testable code and cleaner controllers}
|
13
|
+
|
14
|
+
s.rubyforge_project = "filter_object"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "filter_object/version"
|
2
|
+
require "forwardable"
|
3
|
+
|
4
|
+
module FilterObject
|
5
|
+
module Filter
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@controller, :params, :request, :flash, :redirect_to, :render, :session, :headers, :cookies
|
9
|
+
|
10
|
+
attr_reader :controller
|
11
|
+
|
12
|
+
def filter(controller)
|
13
|
+
@controller = controller
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FilterObject::Filter do
|
4
|
+
class FilterObjectTestClass
|
5
|
+
include FilterObject::Filter
|
6
|
+
end
|
7
|
+
|
8
|
+
subject { FilterObjectTestClass.new }
|
9
|
+
|
10
|
+
let(:controller) { stub }
|
11
|
+
|
12
|
+
it { should respond_to(:filter) }
|
13
|
+
|
14
|
+
describe "#filter" do
|
15
|
+
let(:filter_object) { FilterObjectTestClass.new }
|
16
|
+
|
17
|
+
def run_filter
|
18
|
+
filter_object.filter controller
|
19
|
+
end
|
20
|
+
|
21
|
+
it "configures the filter's controller" do
|
22
|
+
expect { filter_object.filter controller }.to change { filter_object.controller }.to controller
|
23
|
+
end
|
24
|
+
|
25
|
+
context "#params delegation" do
|
26
|
+
before do
|
27
|
+
def filter_object.filter(controller)
|
28
|
+
super
|
29
|
+
params
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "delegates calls to #params to the controller" do
|
34
|
+
controller.should_receive(:params)
|
35
|
+
run_filter
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "#request delegation" do
|
40
|
+
before do
|
41
|
+
def filter_object.filter(controller)
|
42
|
+
super
|
43
|
+
request
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "delegates calls to #request to the controller" do
|
48
|
+
controller.should_receive(:request)
|
49
|
+
run_filter
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "#flash delegation" do
|
54
|
+
before do
|
55
|
+
def filter_object.filter(controller)
|
56
|
+
super
|
57
|
+
flash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "delegates calls to #flash to the controller" do
|
62
|
+
controller.should_receive(:flash)
|
63
|
+
run_filter
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "#redirect_to delegation" do
|
68
|
+
before do
|
69
|
+
def filter_object.filter(controller)
|
70
|
+
super
|
71
|
+
redirect_to
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "delegates calls to #redirect_to to the controller" do
|
76
|
+
controller.should_receive(:redirect_to)
|
77
|
+
run_filter
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "#render delegation" do
|
82
|
+
before do
|
83
|
+
def filter_object.filter(controller)
|
84
|
+
super
|
85
|
+
render
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "delegates calls to #render to the controller" do
|
90
|
+
controller.should_receive(:render)
|
91
|
+
run_filter
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "#session delegation" do
|
96
|
+
before do
|
97
|
+
def filter_object.filter(controller)
|
98
|
+
super
|
99
|
+
session
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "delegates calls to #session to the controller" do
|
104
|
+
controller.should_receive(:session)
|
105
|
+
run_filter
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "#headers delegation" do
|
110
|
+
before do
|
111
|
+
def filter_object.filter(controller)
|
112
|
+
super
|
113
|
+
headers
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "delegates calls to #headers to the controller" do
|
118
|
+
controller.should_receive(:headers)
|
119
|
+
run_filter
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "#cookies delegation" do
|
124
|
+
before do
|
125
|
+
def filter_object.filter(controller)
|
126
|
+
super
|
127
|
+
cookies
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "delegates calls to #cookies to the controller" do
|
132
|
+
controller.should_receive(:cookies)
|
133
|
+
run_filter
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "calling undefined methods" do
|
138
|
+
before do
|
139
|
+
def filter_object.filter(controller)
|
140
|
+
super
|
141
|
+
whatever
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it "does not delegate calls to unknown methods" do
|
146
|
+
expect { run_filter }.to raise_error(NameError)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: filter_object
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Cássio Marques
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2160672660 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2160672660
|
25
|
+
description: You can use filter_object to write classes whose instances encapsulate
|
26
|
+
your filter logic, so you can have testable code and cleaner controllers
|
27
|
+
email:
|
28
|
+
- cassiommc@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- .rspec
|
35
|
+
- Gemfile
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- filter_object.gemspec
|
39
|
+
- lib/filter_object.rb
|
40
|
+
- lib/filter_object/version.rb
|
41
|
+
- spec/filter_object_spec.rb
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
homepage: ''
|
44
|
+
licenses: []
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project: filter_object
|
63
|
+
rubygems_version: 1.8.15
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Create objects to handle filter logic and clean up your controllers
|
67
|
+
test_files:
|
68
|
+
- spec/filter_object_spec.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
has_rdoc:
|