Agile Web Development with Rails, Edition 4
Table of Contents
14.3 Iteration I3: Limiting Access
14.4 Iteration I4: Adding a Sidebar
Expected at least 1 element matching "legend", found 0.
<0> expected to be
>=
<1>.
Traceback:
/home/rubys/git/awdwr/edition4/checkdepot.rb:353:in `block in <class:DepotTest>'
Add admin links and a button to Logout
edit app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body class="<%= controller.controller_name %>">
<div id="banner">
<%= image_tag("logo.png") %>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<% if @cart %>
<%= hidden_div_if(@cart.line_items.empty?, id: 'cart') do %>
<%= render @cart %>
<% end %>
<% end %>
<%= render Order.find(session[:order_id]) if session[:order_id] -%>
<ul>
<li><a href="http://www....">Home</a></li>
<li><a href="http://www..../faq">Questions</a></li>
<li><a href="http://www..../news">News</a></li>
<li><a href="http://www..../contact">Contact</a></li>
</ul>
<% if session[:user_id] %>
<ul>
<li><%= link_to 'Orders', orders_path %></li>
<li><%= link_to 'Products', products_path %></li>
<li><%= link_to 'Users', users_path %></li>
</ul>
<%= button_to 'Logout', logout_path, method: :delete %>
<% end %>
</div>
<div id="main">
<%= yield %>
</div>
</div>
</body>
</html>
Log out
get /admin
Pragmatic Bookshelf
Welcome
It's 2016-01-27 15:57:02 -0500
We have 0 orders.
post /logout
ActionController::InvalidAuthenticityToken
in SessionsController#destroy
ActionController::InvalidAuthenticityToken
Extracted source (around line #195 ):
193
194
195
196
197
198
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
end
end
Extracted source (around line #223 ):
221
222
223
224
225
226
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
#:nodoc:
Extracted source (around line #218 ):
216
217
218
219
220
221
logger.warn "Can't verify CSRF token authenticity"
end
handle_unverified_request
end
end
Extracted source (around line #382 ):
380
381
382
383
384
385
case filter
when Symbol
lambda { |target, _, &blk| target.send filter, &blk }
when String
l = eval "lambda { |value| #{filter} }"
lambda { |target, value| target.instance_exec(value, &l) }
Extracted source (around line #169 ):
167
168
169
170
171
172
unless halted
result_lambda = -> { user_callback.call target, value }
env.halted = halted_lambda.call(target, result_lambda)
if env.halted
Extracted source (around line #12 ):
10
11
12
13
14
15
included do
define_callbacks :process_action,
terminator: ->(controller, result_lambda) { result_lambda.call if result_lambda.is_a?(Proc); controller.response_body },
skip_after_callbacks_if_terminated: true
end
Extracted source (around line #170 ):
168
169
170
171
172
173
unless halted
result_lambda = -> { user_callback.call target, value }
env.halted = halted_lambda.call(target, result_lambda)
if env.halted
target.send :halted_callback_hook, filter
Extracted source (around line #454 ):
452
453
454
455
456
457
def call(arg)
@before.each { |b| b.call(arg) }
value = @call.call(arg)
@after.each { |a| a.call(arg) }
value
Extracted source (around line #454 ):
452
453
454
455
456
457
def call(arg)
@before.each { |b| b.call(arg) }
value = @call.call(arg)
@after.each { |a| a.call(arg) }
value
Extracted source (around line #454 ):
452
453
454
455
456
457
def call(arg)
@before.each { |b| b.call(arg) }
value = @call.call(arg)
@after.each { |a| a.call(arg) }
value
Extracted source (around line #101 ):
99
100
101
102
103
104
runner = callbacks.compile
e = Filters::Environment.new(self, false, nil, block)
runner.call(e).value
end
end
Extracted source (around line #750 ):
748
749
750
751
752
753
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def _run_#{name}_callbacks(&block)
__run_callbacks__(_#{name}_callbacks, &block)
end
RUBY
end
Extracted source (around line #90 ):
88
89
90
91
92
93
# end
def run_callbacks(kind, &block)
send "_run_#{kind}_callbacks", &block
end
private
Extracted source (around line #19 ):
17
18
19
20
21
22
# process_action callbacks around the normal behavior.
def process_action(*args)
run_callbacks(:process_action) do
super
end
end
Extracted source (around line #27 ):
25
26
27
28
29
30
private
def process_action(*args)
super
rescue Exception => exception
request.env['action_dispatch.show_detailed_exceptions'] ||= show_detailed_exceptions?
rescue_with_handler(exception) || raise(exception)
Extracted source (around line #31 ):
29
30
31
32
33
34
ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
begin
result = super
payload[:status] = response.status
result
ensure
Extracted source (around line #164 ):
162
163
164
165
166
167
def instrument(name, payload = {})
if notifier.listening?(name)
instrumenter.instrument(name, payload) { yield payload if block_given? }
else
yield payload if block_given?
end
Extracted source (around line #21 ):
19
20
21
22
23
24
listeners_state = start name, payload
begin
yield payload
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
Extracted source (around line #164 ):
162
163
164
165
166
167
def instrument(name, payload = {})
if notifier.listening?(name)
instrumenter.instrument(name, payload) { yield payload if block_given? }
else
yield payload if block_given?
end
Extracted source (around line #29 ):
27
28
29
30
31
32
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)
ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
begin
result = super
payload[:status] = response.status
Extracted source (around line #248 ):
246
247
248
249
250
251
request.filtered_parameters.merge! wrapped_filtered_hash
end
super
end
private
Extracted source (around line #18 ):
16
17
18
19
20
21
# and it won't be cleaned up by the method below.
ActiveRecord::LogSubscriber.reset_runtime
super
end
def cleanup_view_runtime
Extracted source (around line #128 ):
126
127
128
129
130
131
@_response_body = nil
process_action(action_name, *args)
end
# Delegates to the class' ::controller_path
Extracted source (around line #30 ):
28
29
30
31
32
33
def process(*) #:nodoc:
old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context)
super
ensure
I18n.config = old_config
end
Extracted source (around line #192 ):
190
191
192
193
194
195
set_request!(request)
set_response!(response)
process(name)
request.commit_flash
to_a
end
Extracted source (around line #264 ):
262
263
264
265
266
267
middleware_stack.build(name) { |env| new.dispatch(name, req, res) }.call req.env
else
new.dispatch(name, req, res)
end
end
end
Extracted source (around line #50 ):
48
49
50
51
52
53
def dispatch(controller, action, req, res)
controller.dispatch(action, req, res)
end
end
Extracted source (around line #32 ):
30
31
32
33
34
35
controller = controller req
res = controller.make_response! req
dispatch(controller, params[:action], req, res)
rescue ActionController::RoutingError
if @raise_on_name_error
raise
Extracted source (around line #42 ):
40
41
42
43
44
45
req.path_parameters = set_params.merge parameters
status, headers, body = route.app.serve(req)
if 'pass' == headers['X-Cascade']
req.script_name = script_name
Extracted source (around line #29 ):
27
28
29
30
31
32
def serve(req)
find_routes(req).each do |match, parameters, route|
set_params = req.path_parameters
path_info = req.path_info
script_name = req.script_name
Extracted source (around line #29 ):
27
28
29
30
31
32
def serve(req)
find_routes(req).each do |match, parameters, route|
set_params = req.path_parameters
path_info = req.path_info
script_name = req.script_name
Extracted source (around line #724 ):
722
723
724
725
726
727
req = make_request(env)
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
@router.serve(req)
end
def recognize_path(path, environment = {})
Extracted source (around line #14 ):
12
13
14
15
16
17
def call(env)
ActionView::Digestor.cache.clear
app.call(env)
end
end
Extracted source (around line #25 ):
23
24
25
26
27
28
def call(env)
status, headers, body = @app.call(env)
if etag_status?(status) && etag_body?(body) && !skip_caching?(headers)
original_body = body
Extracted source (around line #38 ):
36
37
38
39
40
41
[status, headers, body]
else
@app.call(env)
end
end
Extracted source (around line #12 ):
10
11
12
13
14
15
def call(env)
status, headers, body = @app.call(env)
if env[REQUEST_METHOD] == HEAD
[
Extracted source (around line #220 ):
218
219
220
221
222
223
req = make_request env
prepare_session(req)
status, headers, body = app.call(req.env)
res = Rack::Response::Raw.new status, headers
commit_session(req, res)
[status, headers, body]
Extracted source (around line #214 ):
212
213
214
215
216
217
def call(env)
context(env)
end
def context(env, app=@app)
Extracted source (around line #608 ):
606
607
608
609
610
611
request = ActionDispatch::Request.new env
status, headers, body = @app.call(env)
if request.have_cookie_jar?
cookie_jar = request.cookie_jar
Extracted source (around line #36 ):
34
35
36
37
38
39
connection.enable_query_cache!
response = @app.call(env)
response[2] = Rack::BodyProxy.new(response[2]) do
restore_query_cache_settings(connection_id, enabled)
end
Extracted source (around line #963 ):
961
962
963
964
965
966
testing = env['rack.test']
status, headers, body = @app.call(env)
proxy = ::Rack::BodyProxy.new(body) do
ActiveRecord::Base.clear_active_connections! unless testing
end
Extracted source (around line #558 ):
556
557
558
559
560
561
end
end
@app.call(env)
end
private
Extracted source (around line #29 ):
27
28
29
30
31
32
result = run_callbacks :call do
begin
@app.call(env)
rescue => error
end
end
Extracted source (around line #97 ):
95
96
97
98
99
100
def __run_callbacks__(callbacks, &block)
if callbacks.empty?
yield if block_given?
else
runner = callbacks.compile
e = Filters::Environment.new(self, false, nil, block)
Extracted source (around line #750 ):
748
749
750
751
752
753
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def _run_#{name}_callbacks(&block)
__run_callbacks__(_#{name}_callbacks, &block)
end
RUBY
end
Extracted source (around line #90 ):
88
89
90
91
92
93
# end
def run_callbacks(kind, &block)
send "_run_#{kind}_callbacks", &block
end
private
Extracted source (around line #27 ):
25
26
27
28
29
30
def call(env)
error = nil
result = run_callbacks :call do
begin
@app.call(env)
rescue => error
Extracted source (around line #71 ):
69
70
71
72
73
74
prepare!
response = @app.call(env)
response[2] = ::Rack::BodyProxy.new(response[2]) { cleanup! }
response
Extracted source (around line #79 ):
77
78
79
80
81
82
req = ActionDispatch::Request.new env
req.remote_ip = GetIp.new(req, check_ip, proxies)
@app.call(req.env)
end
# The GetIp class exists as a way to defer processing of the request data
Extracted source (around line #49 ):
47
48
49
50
51
52
def call(env)
request = ActionDispatch::Request.new env
_, headers, body = response = @app.call(env)
if headers['X-Cascade'] == 'pass'
body.close if body.respond_to?(:close)
Extracted source (around line #131 ):
129
130
131
132
133
134
def call_app(env)
@app.call(env)
rescue => e
throw :app_exception, e
end
Extracted source (around line #28 ):
26
27
28
29
30
31
end
status, headers, body = call_app(env)
if session = Session.from(Thread.current) and acceptable_content_type?(headers)
response = Response.new(body, status, headers)
Extracted source (around line #18 ):
16
17
18
19
20
21
def call(env)
app_exception = catch :app_exception do
request = create_regular_or_whiny_request(env)
return call_app(env) unless request.from_whitelisted_ip?
Extracted source (around line #18 ):
16
17
18
19
20
21
def call(env)
app_exception = catch :app_exception do
request = create_regular_or_whiny_request(env)
return call_app(env) unless request.from_whitelisted_ip?
Extracted source (around line #31 ):
29
30
31
32
33
34
def call(env)
request = ActionDispatch::Request.new env
@app.call(env)
rescue Exception => exception
if request.show_exceptions?
render_exception(request, exception)
Extracted source (around line #42 ):
40
41
42
43
44
45
instrumenter.start 'request.action_dispatch', request: request
logger.info { started_request_message(request) }
resp = @app.call(env)
resp[2] = ::Rack::BodyProxy.new(resp[2]) { finish(request) }
resp
rescue Exception
Extracted source (around line #24 ):
22
23
24
25
26
27
if logger.respond_to?(:tagged)
logger.tagged(compute_tags(request)) { call_app(request, env) }
else
call_app(request, env)
end
Extracted source (around line #70 ):
68
69
70
71
72
73
def tagged(*tags)
formatter.tagged(*tags) { yield self }
end
def flush
Extracted source (around line #26 ):
24
25
26
27
28
29
def tagged(*tags)
new_tags = push_tags(*tags)
yield self
ensure
pop_tags(new_tags.size)
end
Extracted source (around line #70 ):
68
69
70
71
72
73
def tagged(*tags)
formatter.tagged(*tags) { yield self }
end
def flush
Extracted source (around line #24 ):
22
23
24
25
26
27
if logger.respond_to?(:tagged)
logger.tagged(compute_tags(request)) { call_app(request, env) }
else
call_app(request, env)
end
Extracted source (around line #24 ):
22
23
24
25
26
27
req = ActionDispatch::Request.new env
req.request_id = make_request_id(req.x_request_id)
@app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = req.request_id }
end
private
Extracted source (around line #22 ):
20
21
22
23
24
25
end
@app.call(env)
end
def method_override(env)
Extracted source (around line #22 ):
20
21
22
23
24
25
def call(env)
start_time = Utils.clock_time
status, headers, body = @app.call(env)
request_time = Utils.clock_time - start_time
unless headers.has_key?(@header_name)
Extracted source (around line #28 ):
26
27
28
29
30
31
def call(env)
LocalCacheRegistry.set_cache_for(local_cache_key, LocalStore.new)
response = @app.call(env)
response[2] = ::Rack::BodyProxy.new(response[2]) do
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
end
Extracted source (around line #13 ):
11
12
13
14
15
16
interlock = ActiveSupport::Dependencies.interlock
interlock.start_running
response = @app.call(env)
body = Rack::BodyProxy.new(response[2]) { interlock.done_running }
response[2] = body
response
Extracted source (around line #136 ):
134
135
136
137
138
139
end
@app.call(req.env)
end
end
end
Extracted source (around line #111 ):
109
110
111
112
113
114
def call(env)
status, headers, body = @app.call(env)
if body.respond_to?(:to_path)
case type = variation(env)
when 'X-Accel-Redirect'
Extracted source (around line #522 ):
520
521
522
523
524
525
def call(env)
req = build_request env
app.call req.env
end
# Defines additional Rack env configuration that is added on each call.
Extracted source (around line #541 ):
539
540
541
542
543
544
begin
begin
status, headers, res_body = @app.call(env)
return :async if req.hijacked
Extracted source (around line #388 ):
386
387
388
389
390
391
while true
case handle_request(client, buffer)
when false
return
when :async
Extracted source (around line #270 ):
268
269
270
271
272
273
else
if process_now
process_client client, buffer
else
client.set_timeout @first_data_timeout
@reactor.add client
Extracted source (around line #106 ):
104
105
106
107
108
109
begin
block.call(work, *extra)
rescue Exception
end
end
Rails.root: /home/rubys/git/awdwr/edition4/work-230/depot
Request
Parameters :
{"submit"=>"Logout", "_method"=>"delete", "authenticity_token"=>"NmMmmjZubV6FCAJaxpNdMR8zlZm3qdUCzo3B7CKkQI8k6OM37fJEkIqDKTxbA4Of2z+yU/9WYV9Sb9+lb0i8vQ=="}
_csrf_token: "u70b4cghf6vBhb0o9ek+1v+ZllSLc8zQEv3YTxsPx2o="
session_id: "b519f56909f0cc26d35e76b9481983db"
user_id: 1
GATEWAY_INTERFACE: "CGI/1.2"
HTTP_ACCEPT: "*/*"
HTTP_ACCEPT_ENCODING: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
HTTP_VERSION: "HTTP/1.1"
ORIGINAL_SCRIPT_NAME: ""
REMOTE_ADDR: "127.0.0.1"
SERVER_NAME: "localhost"
SERVER_PROTOCOL: "HTTP/1.1"
Response
Headers :
None
Demonstrate that everybody can get to the store
get /
Getting started
Here’s how to get rolling:
Use bin/rails generate
to create your models and controllers
To see all available options, run it without parameters.
Set up a root route to replace this page
You're seeing this page because you're running in development mode and you haven't set a root route yet.
Routes are set up in config/routes.rb .
Configure your database
If you're not using SQLite (the default), edit config/database.yml with your username and password.
Demonstrate that login is required to see the products
get /products
cleanup - precompile assets for inclusion in results
rails assets:precompile
I, [2016-01-27T15:59:04.419567 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/cs-f56ef62bc41b040664e801a38f068082a75d506d9048307e8096737463503d0b.jpg
I, [2016-01-27T15:59:04.420653 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/logo-c6cc13d09c4262e637d9af74fa20f7cc0ba8cb57864863b3ce3135f37cbf308c.png
I, [2016-01-27T15:59:04.421413 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/rails-5ad6d454af23f597c4c39dbe4ec6e12784f8e382997a4bc04944ab8547d48881.png
I, [2016-01-27T15:59:04.422305 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/rtp-d3d2240713cce773840785de837acf822d235d1b77040a3e1ed9d8c014cff086.jpg
I, [2016-01-27T15:59:04.423289 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/ruby-836fee16e3757bcd4e2c21d064eee4fa81d7f93e4e9a44b1ffcd6c1d41c92a88.jpg
I, [2016-01-27T15:59:04.481858 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/application-0beb6360ef0a32f1a2822b8e916d122f46fe74a40ec6c7d7cef590875251d588.js
I, [2016-01-27T15:59:04.481983 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/application-0beb6360ef0a32f1a2822b8e916d122f46fe74a40ec6c7d7cef590875251d588.js.gz
I, [2016-01-27T15:59:04.492874 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/application-681214d51f84f98994bcbc030a95533f0a9fc3172883389ce13e3ec6bcfe66e6.css
I, [2016-01-27T15:59:04.493003 #8488] INFO -- : Writing /home/rubys/git/awdwr/edition4/work-230/depot/public/assets/application-681214d51f84f98994bcbc030a95533f0a9fc3172883389ce13e3ec6bcfe66e6.css.gz
Log in
get /login
#<Errno::ECONNREFUSED: Failed to open TCP connection to localhost:3000 (Connection refused - connect(2) for "localhost" port 3000)>
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:882:in `rescue in block in connect'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:879:in `block in connect'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/timeout.rb:91:in `block in timeout'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/timeout.rb:101:in `timeout'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:878:in `connect'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:863:in `do_start'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:852:in `start'
/home/rubys/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/net/http.rb:584:in `start'
/home/rubys/git/gorp/lib/gorp/net.rb:107:in `post'
makedepot.rb:3117:in `block in <main>'
/home/rubys/git/gorp/lib/gorp/output.rb:59:in `block (4 levels) in <top (required)>'
/home/rubys/git/gorp/lib/gorp/output.rb:49:in `each'
/home/rubys/git/gorp/lib/gorp/output.rb:49:in `block (3 levels) in <top (required)>'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:175:in `_nested_structures'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:68:in `tag!'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:93:in `method_missing'
/home/rubys/git/gorp/lib/gorp/output.rb:22:in `block (2 levels) in <top (required)>'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:175:in `_nested_structures'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:68:in `tag!'
/home/rubys/.rvm/gems/ruby-2.3.0/gems/builder-3.2.2/lib/builder/xmlbase.rb:93:in `method_missing'
/home/rubys/git/gorp/lib/gorp/output.rb:11:in `block in <top (required)>'
Table of Contents
14.3 Iteration I3: Limiting Access