rory 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rory.rb +1 -4
- data/lib/rory/application.rb +41 -16
- data/lib/rory/parameter_filter.rb +64 -0
- data/lib/rory/request_parameter_logger.rb +58 -0
- data/lib/rory/version.rb +1 -1
- data/rory.gemspec +8 -6
- data/spec/fixture_app/config/application.rb +1 -0
- data/spec/fixture_app/log/test.log +0 -0
- data/spec/lib/rory/application_spec.rb +120 -47
- data/spec/lib/rory/controller_spec.rb +1 -1
- data/spec/lib/rory/parameter_filter_spec.rb +50 -0
- data/spec/lib/rory/renderer_spec.rb +11 -9
- data/spec/lib/rory/request_parameter_logger_spec.rb +95 -0
- data/spec/lib/rory_spec.rb +4 -2
- data/spec/spec_helper.rb +1 -1
- metadata +57 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40ba6de912d0a2eff585bacee9ac6e17583bf70c
|
4
|
+
data.tar.gz: de1a192df73c293d81945d0f015173c3e338484e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 864bb31119f46b7f067df7dcb60779844b53efd383f8a40de18376054abb36263694a19b9f40fc0414fcf7ce36577a83a59d55e7f03cedf23e170309a409a2c1
|
7
|
+
data.tar.gz: 23e76ae90efc1de98ecd4cd629ca64624eccc09576156d7cc7a647de7ab07a05326890b9fea1b54304e81138e997c86c51e347a7613a4b8f00e578ca017a08a0
|
data/lib/rory.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
ENV['RORY_ENV'] ||= ENV['RACK_ENV'] || 'development'
|
2
2
|
|
3
|
-
if ENV['RORY_STAGE']
|
4
|
-
raise "Use of 'RORY_STAGE' no longer supported. Use 'RORY_ENV' instead."
|
5
|
-
end
|
6
|
-
|
7
3
|
require 'yaml'
|
8
4
|
require 'sequel'
|
5
|
+
require 'rack/contrib'
|
9
6
|
require 'rory/application'
|
10
7
|
require 'rory/dispatcher'
|
11
8
|
require 'rory/route'
|
data/lib/rory/application.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'logger'
|
3
3
|
require 'rory/route_mapper'
|
4
|
+
require 'rack/commonlogger'
|
5
|
+
require_relative 'request_parameter_logger'
|
6
|
+
|
4
7
|
|
5
8
|
module Rory
|
6
9
|
# Main application superclass. Applications should subclass this class,
|
@@ -17,9 +20,9 @@ module Rory
|
|
17
20
|
private :new
|
18
21
|
attr_reader :root
|
19
22
|
|
20
|
-
def inherited(
|
23
|
+
def inherited(subclass)
|
21
24
|
super
|
22
|
-
Rory.application =
|
25
|
+
Rory.application = subclass.instance
|
23
26
|
end
|
24
27
|
|
25
28
|
def method_missing(*args, &block)
|
@@ -59,9 +62,11 @@ module Rory
|
|
59
62
|
end
|
60
63
|
|
61
64
|
def config_path
|
62
|
-
@config_path ||=
|
63
|
-
|
64
|
-
|
65
|
+
@config_path ||= root_path.join('config')
|
66
|
+
end
|
67
|
+
|
68
|
+
def log_path
|
69
|
+
@log_path ||= root_path.join('log')
|
65
70
|
end
|
66
71
|
|
67
72
|
def set_routes(&block)
|
@@ -96,6 +101,7 @@ module Rory
|
|
96
101
|
end
|
97
102
|
|
98
103
|
def use_middleware(*args, &block)
|
104
|
+
@stack = nil
|
99
105
|
middleware << [args, block]
|
100
106
|
end
|
101
107
|
|
@@ -107,25 +113,44 @@ module Rory
|
|
107
113
|
Rory::Dispatcher.rack_app(self)
|
108
114
|
end
|
109
115
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
116
|
+
def request_logging_on?
|
117
|
+
@request_logging != false
|
118
|
+
end
|
119
|
+
|
120
|
+
def turn_off_request_logging!
|
121
|
+
@stack = nil
|
122
|
+
@request_logging = false
|
123
|
+
end
|
124
|
+
|
125
|
+
def use_default_middleware
|
126
|
+
if request_logging_on?
|
127
|
+
use_middleware Rack::PostBodyContentTypeParser
|
128
|
+
use_middleware Rack::CommonLogger, logger
|
129
|
+
use_middleware Rory::RequestParameterLogger, logger
|
114
130
|
end
|
115
|
-
|
116
|
-
|
131
|
+
end
|
132
|
+
|
133
|
+
def stack
|
134
|
+
@stack ||= Rack::Builder.new.tap { |builder|
|
135
|
+
use_default_middleware
|
136
|
+
middleware.each do |args, block|
|
137
|
+
builder.use *args, &block
|
138
|
+
end
|
139
|
+
builder.run dispatcher
|
140
|
+
}
|
117
141
|
end
|
118
142
|
|
119
143
|
def call(env)
|
120
144
|
stack.call(env)
|
121
145
|
end
|
122
146
|
|
147
|
+
def log_file
|
148
|
+
Dir.mkdir(log_path) unless File.exists?(log_path)
|
149
|
+
File.open(log_path.join("#{ENV['RORY_ENV']}.log"), 'a').tap { |file| file.sync = true }
|
150
|
+
end
|
151
|
+
|
123
152
|
def logger
|
124
|
-
@logger ||=
|
125
|
-
Dir.mkdir('log') unless File.exists?('log')
|
126
|
-
file = File.open(File.join('log', "#{ENV['RORY_ENV']}.log"), 'a')
|
127
|
-
Logger.new(file)
|
128
|
-
end
|
153
|
+
@logger ||= Logger.new(log_file)
|
129
154
|
end
|
130
155
|
end
|
131
156
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Rory
|
2
|
+
class ParameterFilter
|
3
|
+
FILTERED = '[FILTERED]'.freeze
|
4
|
+
|
5
|
+
def initialize(filters = [])
|
6
|
+
@filters = filters
|
7
|
+
end
|
8
|
+
|
9
|
+
def filter(params)
|
10
|
+
compiled_filter.call(params)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def compiled_filter
|
16
|
+
@compiled_filter ||= CompiledFilter.compile(@filters)
|
17
|
+
end
|
18
|
+
|
19
|
+
class CompiledFilter
|
20
|
+
def self.compile(filters)
|
21
|
+
return lambda { |params| params.dup } if filters.empty?
|
22
|
+
|
23
|
+
strings, regexps, blocks = [], [], []
|
24
|
+
|
25
|
+
filters.each do |item|
|
26
|
+
case item
|
27
|
+
when Regexp
|
28
|
+
regexps << item
|
29
|
+
else
|
30
|
+
strings << item.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
regexps << Regexp.new(strings.join('|'), true) unless strings.empty?
|
35
|
+
new regexps, blocks
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :regexps, :blocks
|
39
|
+
|
40
|
+
def initialize(regexps, blocks)
|
41
|
+
@regexps = regexps
|
42
|
+
@blocks = blocks
|
43
|
+
end
|
44
|
+
|
45
|
+
def call(original_params)
|
46
|
+
filtered_params = {}
|
47
|
+
|
48
|
+
original_params.each do |key, value|
|
49
|
+
if regexps.any? { |r| key =~ r }
|
50
|
+
value = FILTERED
|
51
|
+
elsif value.is_a?(Hash)
|
52
|
+
value = call(value)
|
53
|
+
elsif value.is_a?(Array)
|
54
|
+
value = value.map { |v| v.is_a?(Hash) ? call(v) : v }
|
55
|
+
end
|
56
|
+
|
57
|
+
filtered_params[key] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
filtered_params
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative 'parameter_filter'
|
2
|
+
|
3
|
+
module Rory
|
4
|
+
class RequestParameterLogger
|
5
|
+
|
6
|
+
def initialize(app, logger=nil, filters=[:password])
|
7
|
+
@app = app
|
8
|
+
@logger = logger
|
9
|
+
@filters = filters
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
@env = env
|
14
|
+
@env['rack.input'].rewind
|
15
|
+
log_request
|
16
|
+
@app.call(@env)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def log_request
|
22
|
+
log_message(request_signature)
|
23
|
+
log_message("Parameters: #{filtered_params}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def logger
|
27
|
+
@logger || @env['rack.errors']
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_message(message)
|
31
|
+
if logger.respond_to?(:write)
|
32
|
+
logger.write(message + "\n")
|
33
|
+
else
|
34
|
+
logger.info(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parameter_filter
|
39
|
+
Rory::ParameterFilter.new(@filters)
|
40
|
+
end
|
41
|
+
|
42
|
+
def filtered_params
|
43
|
+
parameter_filter.filter(unfiltered_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def request
|
47
|
+
Rack::Request.new(@env)
|
48
|
+
end
|
49
|
+
|
50
|
+
def unfiltered_params
|
51
|
+
request.params
|
52
|
+
end
|
53
|
+
|
54
|
+
def request_signature
|
55
|
+
%{Started #{@env['REQUEST_METHOD']} "#{@env['PATH_INFO']}" for #{@env['REMOTE_ADDR']} at #{Time.now}}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/rory/version.rb
CHANGED
data/rory.gemspec
CHANGED
@@ -28,16 +28,18 @@ EOF
|
|
28
28
|
s.licenses = ["MIT"]
|
29
29
|
s.require_paths = ["lib"]
|
30
30
|
|
31
|
-
s.add_runtime_dependency 'rack', '
|
31
|
+
s.add_runtime_dependency 'rack', '~> 1.0'
|
32
|
+
s.add_runtime_dependency 'rack-contrib', '~> 1.2'
|
32
33
|
s.add_runtime_dependency 'sequel', '~> 4.0'
|
33
34
|
s.add_runtime_dependency 'thin', '~> 1.0'
|
34
35
|
|
35
|
-
s.add_development_dependency 'rake'
|
36
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
36
37
|
s.add_development_dependency 'rspec', '~> 3'
|
37
|
-
s.add_development_dependency 'capybara'
|
38
|
-
s.add_development_dependency 'yard'
|
39
|
-
s.add_development_dependency 'reek'
|
40
|
-
s.add_development_dependency 'simplecov'
|
38
|
+
s.add_development_dependency 'capybara', '~> 2.4'
|
39
|
+
s.add_development_dependency 'yard', '~> 0.8'
|
40
|
+
s.add_development_dependency 'reek', '~> 2.2'
|
41
|
+
s.add_development_dependency 'simplecov', '~> 0.10'
|
41
42
|
s.add_development_dependency 'bundler', '~> 1.0'
|
43
|
+
s.add_development_dependency 'pry', '~> 0.10'
|
42
44
|
end
|
43
45
|
|
File without changes
|
@@ -1,16 +1,23 @@
|
|
1
1
|
describe Rory::Application do
|
2
|
+
let(:subject) {
|
3
|
+
Class.new(Rory::Application).tap { |app|
|
4
|
+
app.root = "whatever"
|
5
|
+
app.turn_off_request_logging!
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
2
9
|
describe ".configure" do
|
3
10
|
it 'yields the given block to self' do
|
4
|
-
|
5
|
-
expect(c).to eq(
|
11
|
+
subject.configure do |c|
|
12
|
+
expect(c).to eq(subject.instance)
|
6
13
|
end
|
7
14
|
end
|
8
15
|
end
|
9
16
|
|
10
17
|
describe '.config_path' do
|
11
18
|
it 'is set to {root}/config by default' do
|
12
|
-
expect(
|
13
|
-
Pathname.new(
|
19
|
+
expect(subject.config_path).to eq(
|
20
|
+
Pathname.new(subject.root).join('config')
|
14
21
|
)
|
15
22
|
end
|
16
23
|
|
@@ -20,64 +27,112 @@ describe Rory::Application do
|
|
20
27
|
expect {
|
21
28
|
RootlessApp.config_path
|
22
29
|
}.to raise_error(RootlessApp::RootNotConfigured)
|
23
|
-
Rory.application =
|
30
|
+
Rory.application = subject.instance
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.log_path' do
|
35
|
+
it 'is set to {root}/config by default' do
|
36
|
+
expect(subject.log_path).to eq(
|
37
|
+
Pathname.new(subject.root).join('log')
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises exception if root not set' do
|
42
|
+
Rory.application = nil
|
43
|
+
class RootlessApp < Rory::Application; end
|
44
|
+
expect {
|
45
|
+
RootlessApp.config_path
|
46
|
+
}.to raise_error(RootlessApp::RootNotConfigured)
|
47
|
+
Rory.application = subject.instance
|
24
48
|
end
|
25
49
|
end
|
26
50
|
|
27
51
|
describe ".respond_to?" do
|
28
52
|
it 'returns true if the instance said so' do
|
29
|
-
expect(
|
30
|
-
expect(
|
53
|
+
expect(subject.instance).to receive(:respond_to?).with(:goat).and_return(true)
|
54
|
+
expect(subject.respond_to?(:goat)).to be_truthy
|
31
55
|
end
|
32
56
|
|
33
57
|
it 'does the usual thing if instance says no' do
|
34
|
-
expect(
|
35
|
-
expect(
|
36
|
-
expect(
|
58
|
+
expect(subject.instance).to receive(:respond_to?).twice.and_return(false)
|
59
|
+
expect(subject.respond_to?(:to_s)).to be_truthy
|
60
|
+
expect(subject.respond_to?(:obviously_not_a_real_method)).to be_falsey
|
37
61
|
end
|
38
62
|
end
|
39
63
|
|
40
64
|
describe ".call" do
|
41
65
|
it "forwards arg to new dispatcher, and calls dispatch" do
|
42
66
|
dispatcher = double(:dispatch => :expected)
|
43
|
-
rack_request = double
|
44
|
-
|
45
|
-
|
46
|
-
expect(
|
67
|
+
rack_request = double(:media_type => 'application/json')
|
68
|
+
env = { "rack.input" => double(:read => {}) }
|
69
|
+
allow(Rack::Request).to receive(:new).with(env).and_return(rack_request)
|
70
|
+
expect(Rory::Dispatcher).to receive(:new).with(rack_request, subject.instance).and_return(dispatcher)
|
71
|
+
expect(subject.call(env)).to eq(:expected)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe ".log_file" do
|
76
|
+
it "creates the log file directory if it does not exist" do
|
77
|
+
file = double(:sync= => true)
|
78
|
+
allow(File).to receive(:exists?).and_return(false)
|
79
|
+
allow(Dir).to receive(:mkdir).and_return(true)
|
80
|
+
allow(File).to receive(:open).and_return(file)
|
81
|
+
expect(subject.log_file).to eq(file)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns the file and does not create the log file directory if it does not exist" do
|
85
|
+
file = double(:sync= => true)
|
86
|
+
allow(File).to receive(:exists?).and_return(true)
|
87
|
+
allow(File).to receive(:open).and_return(file)
|
88
|
+
expect(subject.log_file).to eq(file)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe ".logger" do
|
93
|
+
it "reutrns a logger" do
|
94
|
+
logger = double
|
95
|
+
allow_any_instance_of(subject).to receive(:log_file)
|
96
|
+
allow(Logger).to receive(:new).and_return(logger)
|
97
|
+
expect(subject.logger).to eq(logger)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe ".use_default_middleware" do
|
102
|
+
it "adds middleware when request logging is on" do
|
103
|
+
allow(subject.instance).to receive(:request_logging_on?).and_return(true)
|
104
|
+
allow(subject.instance).to receive(:logger).and_return(:the_logger)
|
105
|
+
subject.use_default_middleware
|
106
|
+
expect(subject.middleware.count).to_not eq(0)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "does not add middleware when request logging is off" do
|
110
|
+
allow(subject.instance).to receive(:request_logging_on?).and_return(false)
|
111
|
+
allow(subject.instance).to receive(:logger).and_return(:the_logger)
|
112
|
+
subject.use_default_middleware
|
113
|
+
expect(subject.middleware.count).to eq(0)
|
47
114
|
end
|
48
115
|
end
|
49
116
|
|
50
117
|
describe ".load_config_data" do
|
51
118
|
it "returns parsed yaml file with given name from directory at config_path" do
|
52
|
-
allow_any_instance_of(
|
119
|
+
allow_any_instance_of(subject).to receive(:config_path).and_return('Africa the Great')
|
53
120
|
allow(YAML).to receive(:load_file).with(
|
54
121
|
File.expand_path(File.join('Africa the Great', 'foo_type.yml'))).
|
55
122
|
and_return(:oscar_the_grouch_takes_a_nap)
|
56
|
-
expect(
|
123
|
+
expect(subject.load_config_data(:foo_type)).to eq(:oscar_the_grouch_takes_a_nap)
|
57
124
|
end
|
58
125
|
end
|
59
126
|
|
60
127
|
describe ".connect_db" do
|
61
128
|
it "sets up sequel connection to DB from YAML file" do
|
62
129
|
config = { 'development' => :expected }
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
describe ".routes" do
|
70
|
-
it "generates a collection of routing objects from route configuration" do
|
71
|
-
expect(Fixture::Application.routes).to eq [
|
72
|
-
Rory::Route.new('foo/:id/bar', :to => 'foo#bar', :methods => [:get, :post]),
|
73
|
-
Rory::Route.new('this/:path/is/:very_awesome', :to => 'awesome#rad'),
|
74
|
-
Rory::Route.new('lumpies/:lump', :to => 'lumpies#show', :methods => [:get], :module => 'goose'),
|
75
|
-
Rory::Route.new('rabbits/:chew', :to => 'rabbits#chew', :methods => [:get], :module => 'goose/wombat'),
|
76
|
-
Rory::Route.new('', :to => 'root#vegetable', :methods => [:get]),
|
77
|
-
Rory::Route.new('', :to => 'root#no_vegetable', :methods => [:delete]),
|
78
|
-
Rory::Route.new('for_reals/switching', :to => 'for_reals#switching', :methods => [:get]),
|
79
|
-
Rory::Route.new('for_reals/:parbles', :to => 'for_reals#srsly', :methods => [:get])
|
80
|
-
]
|
130
|
+
logger_array = []
|
131
|
+
allow(subject.instance).to receive(:logger).and_return(:the_logger)
|
132
|
+
allow(subject.instance).to receive(:load_config_data).with(:database).and_return(config)
|
133
|
+
expect(Sequel).to receive(:connect).with(:expected).and_return(double(:loggers => logger_array))
|
134
|
+
subject.connect_db('development')
|
135
|
+
expect(logger_array).to match_array([:the_logger])
|
81
136
|
end
|
82
137
|
end
|
83
138
|
|
@@ -90,43 +145,61 @@ describe Rory::Application do
|
|
90
145
|
|
91
146
|
describe '.auto_require_paths' do
|
92
147
|
after(:each) do
|
93
|
-
|
148
|
+
subject.instance.instance_variable_set(:@auto_require_paths, nil)
|
94
149
|
end
|
95
150
|
|
96
151
|
it 'includes models, controllers, and helpers by default' do
|
97
|
-
expect(
|
152
|
+
expect(subject.auto_require_paths).to eq(['models', 'controllers', 'helpers'])
|
98
153
|
end
|
99
154
|
|
100
155
|
it 'accepts new paths' do
|
101
|
-
|
102
|
-
expect(
|
156
|
+
subject.auto_require_paths << 'chocolates'
|
157
|
+
expect(subject.auto_require_paths).to eq(['models', 'controllers', 'helpers', 'chocolates'])
|
103
158
|
end
|
104
159
|
end
|
105
160
|
|
106
161
|
describe '.require_all_files' do
|
107
162
|
it 'requires all files in auto_require_paths' do
|
108
|
-
allow_any_instance_of(
|
163
|
+
allow_any_instance_of(subject).to receive(:auto_require_paths).and_return(['goats', 'rhubarbs'])
|
109
164
|
[:goats, :rhubarbs].each do |folder|
|
110
165
|
expect(Rory::Support).to receive(:require_all_files_in_directory).
|
111
|
-
with(Pathname.new(
|
166
|
+
with(Pathname.new(subject.root).join("#{folder}"))
|
112
167
|
end
|
113
|
-
|
168
|
+
subject.require_all_files
|
114
169
|
end
|
115
170
|
end
|
116
171
|
|
117
172
|
describe '.use_middleware' do
|
118
173
|
it 'adds the given middleware to the stack, retaining args and block' do
|
119
|
-
|
120
|
-
|
174
|
+
require_relative '../../fixture_app/lib/dummy_middleware'
|
175
|
+
subject.use_middleware DummyMiddleware, :puppy do |dm|
|
121
176
|
dm.prefix = 'a salubrious'
|
122
177
|
end
|
123
178
|
|
124
|
-
expect(
|
179
|
+
expect(subject.instance).to receive(:dispatcher).
|
125
180
|
and_return(dispatch_stack_mock = double)
|
126
181
|
expect(dispatch_stack_mock).to receive(:call).
|
127
182
|
with('a salubrious puppy')
|
128
|
-
|
129
|
-
|
183
|
+
subject.call({})
|
184
|
+
subject.middleware.clear
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "with fixture application" do
|
189
|
+
subject { Fixture::Application }
|
190
|
+
describe ".routes" do
|
191
|
+
it "generates a collection of routing objects from route configuration" do
|
192
|
+
expect(subject.routes).to eq [
|
193
|
+
Rory::Route.new('foo/:id/bar', :to => 'foo#bar', :methods => [:get, :post]),
|
194
|
+
Rory::Route.new('this/:path/is/:very_awesome', :to => 'awesome#rad'),
|
195
|
+
Rory::Route.new('lumpies/:lump', :to => 'lumpies#show', :methods => [:get], :module => 'goose'),
|
196
|
+
Rory::Route.new('rabbits/:chew', :to => 'rabbits#chew', :methods => [:get], :module => 'goose/wombat'),
|
197
|
+
Rory::Route.new('', :to => 'root#vegetable', :methods => [:get]),
|
198
|
+
Rory::Route.new('', :to => 'root#no_vegetable', :methods => [:delete]),
|
199
|
+
Rory::Route.new('for_reals/switching', :to => 'for_reals#switching', :methods => [:get]),
|
200
|
+
Rory::Route.new('for_reals/:parbles', :to => 'for_reals#srsly', :methods => [:get])
|
201
|
+
]
|
202
|
+
end
|
130
203
|
end
|
131
204
|
end
|
132
|
-
end
|
205
|
+
end
|
@@ -215,7 +215,7 @@ describe Rory::Controller do
|
|
215
215
|
|
216
216
|
describe "#generate_body_from_template" do
|
217
217
|
it "returns rendered template with given name" do
|
218
|
-
expect(subject.generate_body_from_template('test/letsgo')).to eq("Let's go content")
|
218
|
+
expect(subject.generate_body_from_template('test/letsgo', :app => Fixture::Application)).to eq("Let's go content")
|
219
219
|
end
|
220
220
|
|
221
221
|
it "returns renderer output" do
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe Rory::ParameterFilter do
|
2
|
+
|
3
|
+
describe '#initialize' do
|
4
|
+
it 'sets the filters' do
|
5
|
+
expect(subject.instance_variable_get(:@filters)).to eq []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#filter' do
|
10
|
+
it 'returns params unchanged' do
|
11
|
+
unfiltered_params = {"address"=>"11802 MCDONALD ST, Los Angeles, CA 90230",
|
12
|
+
"owners"=>[{"first_name"=>"GOLD", "last_name"=>"PATH", "ssn"=>"000-02-9999"}],
|
13
|
+
"overrides"=>{"ofac_7403"=>"clear"}}
|
14
|
+
|
15
|
+
expect(subject.filter(unfiltered_params)).to eq unfiltered_params
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns params filtered by' do
|
19
|
+
subject = described_class.new([:ssn])
|
20
|
+
unfiltered_params = {"address"=>"11802 MCDONALD ST, Los Angeles, CA 90230",
|
21
|
+
"owners"=>[{"first_name"=>"GOLD", "last_name"=>"PATH", "ssn"=>"000-02-9999"}],
|
22
|
+
"overrides"=>{"ofac_7403"=>"clear"}}
|
23
|
+
|
24
|
+
filtered_params = {"address"=>"11802 MCDONALD ST, Los Angeles, CA 90230",
|
25
|
+
"owners"=>[{"first_name"=>"GOLD", "last_name"=>"PATH", "ssn"=>"[FILTERED]"}],
|
26
|
+
"overrides"=>{"ofac_7403"=>"clear"}}
|
27
|
+
|
28
|
+
|
29
|
+
expect(subject.filter(unfiltered_params)).to eq filtered_params
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'filters based upon regex' do
|
33
|
+
|
34
|
+
filter_words = []
|
35
|
+
filter_words << /ofac*/
|
36
|
+
|
37
|
+
subject = described_class.new(filter_words)
|
38
|
+
|
39
|
+
unfiltered_params = {:address=>"11802 MCDONALD ST, Los Angeles, CA 90230",
|
40
|
+
"owners"=>[{"first_name"=>"GOLD", "last_name"=>"PATH", "ssn"=>"000-02-9999"}],
|
41
|
+
"overrides"=>{"ofac_7403"=>"clear"}}
|
42
|
+
|
43
|
+
filtered_params = {:address=>"11802 MCDONALD ST, Los Angeles, CA 90230",
|
44
|
+
"owners"=>[{"first_name"=>"GOLD", "last_name"=>"PATH", "ssn"=>"000-02-9999"}],
|
45
|
+
"overrides"=>{"ofac_7403"=>"[FILTERED]"}}
|
46
|
+
|
47
|
+
expect(subject.filter(unfiltered_params)).to eq filtered_params
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,34 +1,36 @@
|
|
1
|
-
describe Rory::Renderer do
|
1
|
+
describe Rory::Renderer do
|
2
2
|
describe "#render" do
|
3
|
+
let(:app) { Fixture::Application }
|
4
|
+
|
3
5
|
it "returns text of template" do
|
4
|
-
renderer = Rory::Renderer.new('test/static')
|
6
|
+
renderer = Rory::Renderer.new('test/static', :app => app)
|
5
7
|
expect(renderer.render).to eq('Static content')
|
6
8
|
end
|
7
9
|
|
8
10
|
it "returns text of template in given layout" do
|
9
|
-
controller = Rory::Renderer.new('test/static', :layout => 'surround')
|
11
|
+
controller = Rory::Renderer.new('test/static', :layout => 'surround', :app => app)
|
10
12
|
expect(controller.render).to eq('Surrounding Static content is fun')
|
11
13
|
end
|
12
14
|
|
13
15
|
it "handles symbolized layout name" do
|
14
|
-
controller = Rory::Renderer.new('test/static', :layout => :surround)
|
16
|
+
controller = Rory::Renderer.new('test/static', :layout => :surround, :app => app)
|
15
17
|
expect(controller.render).to eq('Surrounding Static content is fun')
|
16
18
|
end
|
17
19
|
|
18
20
|
it "exposes locals to template" do
|
19
|
-
controller = Rory::Renderer.new('test/dynamic', :locals => { :word => 'hockey' })
|
21
|
+
controller = Rory::Renderer.new('test/dynamic', :locals => { :word => 'hockey' }, :app => app)
|
20
22
|
expect(controller.render).to eq('Word: hockey')
|
21
23
|
end
|
22
24
|
|
23
25
|
it "can render nested templates" do
|
24
|
-
controller = Rory::Renderer.new('test/double_nested', :locals => { :word => 'hockey' })
|
26
|
+
controller = Rory::Renderer.new('test/double_nested', :locals => { :word => 'hockey' }, :app => app)
|
25
27
|
expect(controller.render).to eq(
|
26
28
|
"Don't Say A Bad Word: Poop!"
|
27
29
|
)
|
28
30
|
end
|
29
31
|
|
30
32
|
it "exposes base_path to template" do
|
31
|
-
controller = Rory::Renderer.new('test/a_link', :base_path => 'spoo')
|
33
|
+
controller = Rory::Renderer.new('test/a_link', :base_path => 'spoo', :app => app)
|
32
34
|
expect(controller.render).to eq('You came from spoo.')
|
33
35
|
end
|
34
36
|
end
|
@@ -41,8 +43,8 @@ describe Rory::Renderer do
|
|
41
43
|
end
|
42
44
|
|
43
45
|
it 'uses Rory.root if no app specified' do
|
44
|
-
renderer = Rory::Renderer.new('goose')
|
45
|
-
expect(renderer.view_path).to eq(File.join(
|
46
|
+
renderer = Rory::Renderer.new('goose', :app => double(:root => "horse"))
|
47
|
+
expect(renderer.view_path).to eq(File.expand_path(File.join('views', 'goose.html.erb'), "horse"))
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
describe Rory::RequestParameterLogger do
|
2
|
+
|
3
|
+
let(:logger) { double(:write) }
|
4
|
+
let(:app) { double(:call) }
|
5
|
+
subject { described_class.new(app, logger, :filters) }
|
6
|
+
|
7
|
+
describe '#initialize' do
|
8
|
+
it 'returns a new RequestParameterLogger' do
|
9
|
+
expect(subject).to be_an_instance_of(Rory::RequestParameterLogger)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns a new RequestParameterLogger with parameters' do
|
13
|
+
expect(subject.instance_variable_get(:@app)).to eq(app)
|
14
|
+
expect(subject.instance_variable_get(:@logger)).to eq(logger)
|
15
|
+
expect(subject.instance_variable_get(:@filters)).to eq(:filters)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#log_request' do
|
20
|
+
|
21
|
+
context 'when logger responds to write' do
|
22
|
+
it 'writes the request to the logger' do
|
23
|
+
allow(subject).to receive(:request_signature).and_return('request_signature')
|
24
|
+
allow(subject).to receive(:filtered_params).and_return('filtered_params')
|
25
|
+
expect(logger).to receive(:write).exactly(2).times
|
26
|
+
subject.send(:log_request)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when logger does not respond to write' do
|
31
|
+
let(:logger) { double(:info) }
|
32
|
+
it 'writes the request to the logger' do
|
33
|
+
allow(subject).to receive(:request_signature).and_return('request_signature')
|
34
|
+
allow(subject).to receive(:filtered_params).and_return('filtered_params')
|
35
|
+
expect(logger).to receive(:info).exactly(2).times
|
36
|
+
subject.send(:log_request)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#logger' do
|
42
|
+
it 'returns @logger' do
|
43
|
+
expect(subject.send(:logger)).to eq(logger)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns rack.errors ' do
|
47
|
+
subject = described_class.new(:app)
|
48
|
+
subject.instance_variable_set(:@env, {'rack.errors' => 'cocoa'})
|
49
|
+
expect(subject.send(:logger)).to eq('cocoa')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#filtered_params' do
|
54
|
+
it 'filters the params' do
|
55
|
+
expect(Rory::ParameterFilter).to receive(:new).and_return(double(:filter => nil))
|
56
|
+
expect(subject).to receive(:unfiltered_params)
|
57
|
+
subject.send(:filtered_params)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#unfiltered_params' do
|
62
|
+
it 'returns unfiltered params' do
|
63
|
+
expect(Rack::Request).to receive(:new).and_return(double(:params => nil))
|
64
|
+
subject.send(:unfiltered_params)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#request_signature' do
|
69
|
+
it 'returns a request signature formatted string' do
|
70
|
+
env = {
|
71
|
+
'REQUEST_METHOD' => "POST",
|
72
|
+
'PATH_INFO' => "/mushy_mushy",
|
73
|
+
'REMOTE_ADDR' => "127.0.0.1"
|
74
|
+
}
|
75
|
+
|
76
|
+
allow(Time).to receive(:now).and_return("2015-06-08 15:16:42 -0700")
|
77
|
+
subject.instance_variable_set(:@env, env)
|
78
|
+
expect(subject.send(:request_signature)).to eq('Started POST "/mushy_mushy" for 127.0.0.1 at 2015-06-08 15:16:42 -0700')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
describe '#call' do
|
84
|
+
it 'writes the request and parameters to the log file' do
|
85
|
+
env = {
|
86
|
+
'rack.input' => double(:rewind => nil)
|
87
|
+
}
|
88
|
+
expect(app).to receive(:call).with(env)
|
89
|
+
expect(subject).to receive(:log_request)
|
90
|
+
|
91
|
+
subject.call(env)
|
92
|
+
expect(subject.instance_variable_get(:@env)).to eq(env)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/spec/lib/rory_spec.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
describe Rory do
|
2
|
+
let!(:new_app) { Class.new(Rory::Application) }
|
3
|
+
|
2
4
|
describe '.application' do
|
3
5
|
it 'is by default set to the Rory::Application instance' do
|
4
|
-
expect(Rory.application).to eq(
|
6
|
+
expect(Rory.application).to eq(new_app.instance)
|
5
7
|
end
|
6
8
|
end
|
7
9
|
|
8
10
|
describe '.root' do
|
9
11
|
it 'returns root of application' do
|
10
|
-
expect(Rory.root).to eq(
|
12
|
+
expect(Rory.root).to eq(new_app.root)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ravi Gadad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack-contrib
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.2'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: sequel
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +70,16 @@ dependencies:
|
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - "
|
73
|
+
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '10.4'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - "
|
80
|
+
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '10.4'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,58 +98,58 @@ dependencies:
|
|
84
98
|
name: capybara
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - "
|
101
|
+
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
103
|
+
version: '2.4'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- - "
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
110
|
+
version: '2.4'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: yard
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
117
|
+
version: '0.8'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- - "
|
122
|
+
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
124
|
+
version: '0.8'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: reek
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- - "
|
129
|
+
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
131
|
+
version: '2.2'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- - "
|
136
|
+
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
138
|
+
version: '2.2'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: simplecov
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
|
-
- - "
|
143
|
+
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
145
|
+
version: '0.10'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
|
-
- - "
|
150
|
+
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
152
|
+
version: '0.10'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: bundler
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +164,20 @@ dependencies:
|
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '1.0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: pry
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.10'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.10'
|
153
181
|
description: |
|
154
182
|
An exercise: Untangle the collusion of Rails idioms
|
155
183
|
from my Ruby knowledge, while trying to understand some
|
@@ -171,9 +199,11 @@ files:
|
|
171
199
|
- lib/rory/application.rb
|
172
200
|
- lib/rory/controller.rb
|
173
201
|
- lib/rory/dispatcher.rb
|
202
|
+
- lib/rory/parameter_filter.rb
|
174
203
|
- lib/rory/path_generation.rb
|
175
204
|
- lib/rory/renderer.rb
|
176
205
|
- lib/rory/renderer/context.rb
|
206
|
+
- lib/rory/request_parameter_logger.rb
|
177
207
|
- lib/rory/route.rb
|
178
208
|
- lib/rory/route_mapper.rb
|
179
209
|
- lib/rory/support.rb
|
@@ -191,6 +221,7 @@ files:
|
|
191
221
|
- spec/fixture_app/controllers/goose/wombat/rabbits_controller.rb
|
192
222
|
- spec/fixture_app/controllers/stub_controller.rb
|
193
223
|
- spec/fixture_app/lib/dummy_middleware.rb
|
224
|
+
- spec/fixture_app/log/test.log
|
194
225
|
- spec/fixture_app/views/for_reals/but_wait.html.erb
|
195
226
|
- spec/fixture_app/views/for_reals/custom.html.erb
|
196
227
|
- spec/fixture_app/views/for_reals/srsly.html.erb
|
@@ -204,8 +235,10 @@ files:
|
|
204
235
|
- spec/lib/rory/application_spec.rb
|
205
236
|
- spec/lib/rory/controller_spec.rb
|
206
237
|
- spec/lib/rory/dispatcher_spec.rb
|
238
|
+
- spec/lib/rory/parameter_filter_spec.rb
|
207
239
|
- spec/lib/rory/renderer/context_spec.rb
|
208
240
|
- spec/lib/rory/renderer_spec.rb
|
241
|
+
- spec/lib/rory/request_parameter_logger_spec.rb
|
209
242
|
- spec/lib/rory/route_spec.rb
|
210
243
|
- spec/lib/rory/support_spec.rb
|
211
244
|
- spec/lib/rory_spec.rb
|