SlideShare a Scribd company logo
1 of 88
Download to read offline
kiev.rb #2

#2
.rb

kiev

Debugging on Rails
Mykhaylo Sorochan
Contents
Debugged application
Sample app for the Ruby on Rails Tutorial (Rails 4)
https://github.com/railstutorial/sample_app_rails_4
debugger
gem 'debugger'
debugger - call debugger
config - .rdebugrc
Debug location
UserController#show

def show
@user = User.find(params[:id])
debugger
@microposts = @user.microposts.paginate(page: params[:page])
end
Debugger commands
(rdb:9) help
ruby-debug help v1.6.2
Type 'help <command-name>' for help on a specific command

Available commands:
backtrace

delete

enable

help

list

pry

restart

source

undisplay

break

disable

eval

info

method

ps

save

start

up

catch

display

exit

irb

next

putl

set

step

var

condition

down

finish

jump

p

quit

show

thread

where

continue

edit

frame

kill

pp

reload

skip

trace
Program info
(rdb:4) help info
Generic command for showing things about the program being debugged.
-List of info subcommands:
-info args -- Argument variables of current stack frame
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
info display -- Expressions to display when program stops
info file -- Info about a particular file read in
info files -- File names and timestamps of files read in
info global_variables -- Global variables
info instance_variables -- Instance variables of the current stack frame
info line -- Line number and file name of current position in source file
info locals -- Local variables of the current stack frame
info program -- Execution status of the program
info stack -- Backtrace of the stack
info thread -- List info about thread NUM
info threads -- information of currently-known threads
info variables -- Local and instance variables of the current stack frame
Listing
(rdb:1) help list
l[ist]

list forward

l[ist] -

list backward

l[ist] =

list current line

l[ist] nn-mm

list given lines

NOTE - to turn on autolist, use 'set autolist' -> .rdebugrc
Listing: in debug
12

@user = User.find(params[:id])

13

debugger

=> 14
15
16

@microposts = @user.microposts.paginate(page: params[:page])
end
Listing: l 23,25
l 23,25
[23, 25] in */sample_app_rails_4/app/controllers/users_controller.rb
23

if @user.save

24

sign_in @user

25

flash[:success] = "Welcome to the Sample App!"
Breakpoints
(rdb:4) help break
b[reak] file:line [if expr]
b[reak] class(.|#)method [if expr]
set breakpoint to some position, (optionally) if expr == true
(rdb:4) help delete
del[ete][ nnn...]

delete some or all breakpoints
Set breakpoint
(rdb:4) b ApplicationHelper#full_title
Breakpoint 1 at ApplicationHelper::full_title
(rdb:4) b 18
Breakpoint 2 file */sample_app_rails_4/app/controllers/users_controller.rb, line 18
(rdb:4) info b
Num Enb What
1 y

at ApplicationHelper:full_title

2 y

at */sample_app_rails_4/app/controllers/users_controller.rb:18
Navigate
(rdb:4) help step
s[tep][+-]?[ nnn]

step (into methods) once or nnn times

'+' forces to move to another line.
'-' is the opposite of '+' and disables the force_stepping setting.
(rdb:4) help next
n[ext][+-]?[ nnn]

step over once or nnn times,

'+' forces to move to another line.
'-' is the opposite of '+' and disables the force_stepping setting.
(rdb:4) help up
up[count]

move to higher frame
Stop at breakpoint
(rdb:4) c
Breakpoint 1 at ApplicationHelper:full_title
[-1, 8] in */sample_app_rails_4/app/helpers/application_helper.rb
1

module ApplicationHelper

2
3
=> 4
5

# Returns the full title on a per-page basis.
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
Display
(rdb:4) help display
disp[lay] <expression>

add expression into display expression list

disp[lay]

display expression list

(rdb:4) help undisplay
undisp[lay][ nnn]
Cancel some expressions to be displayed when program stops.
Display configured
4
=> 5
6

def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?

(rdb:4) disp
2: controller_name = users
3: base_title =
Display changed
(rdb:4) n
*/sample_app_rails_4/app/helpers/application_helper.rb:6
if page_title.empty?

2: controller_name = users
3: base_title = Ruby on Rails Tutorial Sample App
[1, 10] in */sample_app_rails_4/app/helpers/application_helper.rb
5
=> 6
7

base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
Conditional breakpoint
(rdb:8) b ApplicationHelper#full_title if page_title=="Alexander"
Breakpoint 4 at ApplicationHelper::full_title
(rdb:8) c
Breakpoint 1 at ApplicationHelper:full_title
Variables
(rdb:8) help var
v[ar] cl[ass]

show class variables of self

v[ar] co[nst] <object>

show constants of object

v[ar] g[lobal]

show global variables

v[ar] i[nstance] <object>

show instance variables of object. You may pass object id's hex as well.

v[ar] l[ocal]

show local variables
Show variables
12

@user = User.find(params[:id])

13

debugger

=> 14
15

@microposts = @user.microposts.paginate(page: params[:page])
end

16
17

def new

(rdb:12) v i
@_action_has_layout = true
@_action_name = "show"
@_config = {}
@_env = {"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/users/1", "QUERY_STRING"=>"",...
@_headers = {"Content-Type"=>"text/html"}
@_lookup_context = #<ActionView::LookupContext:0x00000008e4b710 @details_key=nil, @details={:loc...
@_params = {"action"=>"show", "controller"=>"users", "id"=>"1"}
@_prefixes = ["users", "application"]
@_request = #<ActionDispatch::Request:0x00000008e4bad0 @env={"GATEWAY_INTERFACE"=>"CGI/1....
@_response = #<ActionDispatch::Response:0x00000008e4baa8 @mon_owner=nil, @mon_count=0, @mo...
@_response_body = nil
@_routes = nil
@_status = 200
@user = #<User id: 1, name: "Alexander", email: "asdf@asdf.com", created_at: "2013-11...
Remote debugger
Server
Debugger.wait_connection = true
Debugger.start_remote

Client
# rdebug --client -h 127.0.0.1
Connected.

*/sample_app_rails_4/app/controllers/users_controller.rb:14
@microposts = @user.microposts.paginate(page: params[:page])

[9, 18] in */sample_app_rails_4/app/controllers/users_controller.rb
9

end

10
11

def show

12

@user = User.find(params[:id])

13

debugger

=> 14

@microposts = @user.microposts.paginate(page: params[:page])
pry
REPL
debugger-pry
Call pry from debugger
pry-debugger
Debugger commands inside pry:
step, next, continue, breakpoints
jazz_hands
jazz_hands is an opinionated set of consolerelated gems and a bit of glue:
pry, awesome_print, hirb, pry-rails, pry-doc, pry-git,
pry-remote, pry-debugger, pry-stack_explorer, coolline,
coderay
pry – jazz_hands 1
pry – jazz_hands 2
pry – jazz_hands 3
pry – jazz_hands 4
Logging
ActiveSupport::Logger

is used for logging

Rails.root/log/[environment_name].log
Log levels
Rails.logger.level

| name

| level |

|----------+-------|
| :debug

|

0 |

| :info

|

1 |

| :warn

|

2 |

| :error

|

3 |

| :fatal

|

4 |

| :unknown |

5 |

development, testing:
production:

log_level = 0 (:debug)

log_level = 1

Messages with equal or higher level are sent to log
Write to log
logger.debug User.inspect
logger.info user.id
logger.fatal "Help!"
Tagging log messages
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged("USER") { logger.info "hello" }
=> [USER] hello
Tagged logging
def show
@user = User.find(params[:id])
logger.tagged("USER") { logger.info @user.email }

# tail -f log/development.log|grep [USER]
[USER] asdf@asdf.com
Global variables for tracing
__FILE__

- file name

__LINE__

- line number
Some useful CLI commands
tail -n 100
tail -f
grep, less
Querying logs
# cat log/development.log|grep GET|tail -n 2
Started GET "/assets/users.js?body=1" for 127.0.0.1 at 2013-11-21 23:32:01 +0200
Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2013-11-21 23:32:01 +0200

# cat log/development.log|grep GET|wc -l
574
config.log_formatter
Defines the formatter of the Rails logger.
Defaults to

ActiveSupport::Logger::SimpleFormatter

production defaults to

for all modes,

Logger::Formatter.

module ActiveSupport
class Logger < ::Logger

# Simple formatter which only displays the message.
class SimpleFormatter < ::Logger::Formatter
# This method is invoked when a log event occurs
def call(severity, timestamp, progname, msg)
"#{String === msg ? msg : msg.inspect}n"
end
end
config.log_level
Defaults to

:debug

for all modes, production defaults to

:info.
config.log_tags
See

ActionDispatch::Request

methods.

config.log_tags = [ :fullpath ]

[/users/1] Started GET "/users/1" for 127.0.0.1 at 2013-11-...
[/users/1]

ActiveRecord::SchemaMigration Load (0.1ms)

SELECT ...

[/assets/application.css?body=1] Started GET "/assets/application.css?body=1" for 127...
config.logger
Accepts a logger conforming to the interface of Log4r or the default Ruby Logger class.
Defaults to

ActiveSupport::Logger,

with auto flushing off in production mode.
Rails console
rails c
rails c --sandbox

irb
pry
rake routes
> all_routes = Rails.application.routes.routes
> require 'action_dispatch/routing/inspector'
> inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
All routes
> puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new)
Prefix Verb

URI Pattern

Controller#Action

following_user GET

/users/:id/following(.:format) users#following

followers_user GET

/users/:id/followers(.:format) users#followers

users GET

/users(.:format)

users#index

/users(.:format)

users#create

/users/new(.:format)

users#new

/users/:id/edit(.:format)

users#edit

/users/:id(.:format)

users#show

PATCH

/users/:id(.:format)

users#update

PUT

/users/:id(.:format)

users#update

POST
new_user GET
edit_user GET
user GET

DELETE /users/:id(.:format)
sessions POST
new_session GET

/sessions(.:format)

sessions#create

/sessions/new(.:format)

sessions#new

session DELETE /sessions/:id(.:format)
microposts POST

/microposts(.:format)

micropost DELETE /microposts/:id(.:format)
relationships POST

/relationships(.:format)

relationship DELETE /relationships/:id(.:format)
root GET
signup GET

users#destroy

sessions#destroy
microposts#create
microposts#destroy
relationships#create
relationships#destroy

/

static_pages#home

/signup(.:format)

users#new
Routes for controller
> puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, 'microposts')
Prefix Verb
microposts POST

URI Pattern

Controller#Action

/microposts(.:format)

microposts#create

micropost DELETE /microposts/:id(.:format) microposts#destroy
Filtering routes: GET
> puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, 'users').lines.grep(/GET/).join
following_user GET

/users/:id/following(.:format) users#following

followers_user GET

/users/:id/followers(.:format) users#followers

users GET
new_user GET
edit_user GET
user GET
signup GET

/users(.:format)

users#index

/users/new(.:format)

users#new

/users/:id/edit(.:format)

users#edit

/users/:id(.:format)

users#show

/signup(.:format)

users#new
Filtering routes: /relation/
> puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new).lines.grep(/relation/).join
relationships POST

/relationships(.:format)

relationship DELETE /relationships/:id(.:format)

relationships#create
relationships#destroy
Matching routes
> r = Rails.application.routes
> r.recognize_path "/users/47"
=> {:action=>"show", :controller=>"users", :id=>"47"}
> r.recognize_path "/users/87", :method => "PUT"
=> {:action=>"update", :controller=>"users", :id=>"87"}
> r.recognize_path "/users/47.json"
=> {:action=>"show", :controller=>"users", :id=>"47", :format=>"json"}
Named routes
> app.users_path
=> "/users"
> app.users_path(:json)
=> "/users.json"
> app.user_path(1)
=> "/users/1"
> app.user_path(1, :xml)
=> "/users/1.xml"
> app.user_path(1, :count => 4)
=> "/users/1?count=4"
Making requests
> app
=> #<ActionDispatch::Integration::Session:...>

> app.reset!
Get requests
> app.get '/users/1/edit'

Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:24:18 +0200
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
Redirected to http://localhost:3000/signin
Filter chain halted as :signed_in_user rendered or redirected
Completed 302 Found in 3ms (ActiveRecord: 0.4ms)

> app.response.body
=> "<html><body>You are being <a href="http://localhost:3000/signin">redirected</a>.</body></html>"

> app.get_via_redirect '/users/1/edit'

Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:26:44 +0200
Redirected to http://localhost:3000/signin
...
Started GET "/signin" for 127.0.0.1 at 2013-11-26 23:26:44 +0200
Session cookies
> app.cookies
=> #<Rack::Test::CookieJar...

> app.cookies.to_hash
=> {"_sample_app_session"=>"RC9j...

app.cookies - received/sent cookies
Post requests: signin
> app.response.body.lines.grep /csrf-token/
=> ["<meta content="n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=" name="csrf-token" />n"]

> app.post '/sessions', :authenticity_token => 'n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=',
'session[email]' => 'asdf@asdf.com', 'session[password]' => '123456'

Started POST "/sessions" for 127.0.0.1 at 2013-11-26 23:33:01 +0200
Processing by SessionsController#create as HTML
Parameters: {"authenticity_token"=>"n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=", "session"=>{"email"
=>"asdf@asdf.com", "password"=>"[FILTERED]"}}
Redirected to http://localhost:3000/users/1/edit
Completed 302 Found in 281ms (ActiveRecord: 7.2ms)

app.post_via_redirect
Access to restricted resource
> app.get '/users/1/edit'

Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:38:47 +0200
Processing by UsersController#edit as HTML
Completed 200 OK in 41ms (Views: 35.7ms | ActiveRecord: 0.8ms)
Call helper
> helper
=> #<ActionView::Base:... >
# ApplicationHelper#full_title
> helper.full_title "Sign Up"
=> "Ruby on Rails Tutorial Sample App | Sign Up"
Call helper with cookie
> def cookies; @cookies ||= HashWithIndifferentAccess.new(app.cookies.to_hash); end

> helper.current_user
=> #<User id: 1, name: ....
ActiveRecord logging
> ActiveRecord::Base.logger = Logger.new(STDOUT)
> ActiveRecord::Base.clear_active_connections!
> # reload!
> User.find 1
D, [2013-12-30T21:55:17.775769 #24810] DEBUG -- :
WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
=> #<User id: 1, name: "hello",....

User Load (0.2ms)

SELECT "users".* FROM "users"
ActiveRecord hide logging
> ActiveRecord::Base.logger = Logger.new(nil)
> ActiveRecord::Base.clear_active_connections!
> # reload!
> User.find 1
=> #<User id: 1, name: "hello",....
Raw SQL requests
> ActiveRecord::Base.connection.select_all("select * from users")
=> #<ActiveRecord::Result:...
> puts _
{"id"=>1, "name"=>"hello", "email"=>"hello@hello.com", "created_at"=>"2013-....
.irbrc
Save your helper methods
● routes
● sql logging
● etc
CLI tools
Making HTTP requests with curl
●
●
●
●
●
●

-s silent
-v verbose
-c save cookie
-b use cookie
-data POST data
-data-urlencode URL-encode POST data
Access restricted area
curl -s -v http://localhost:3000/users/1/edit > /dev/null

> GET /users/1/edit HTTP/1.1
< HTTP/1.1 302 Found
< Location: http://localhost:3000/signin
Visit /signin, get token
curl -s -c hello_cookies http://localhost:3000/signin > /dev/null |grep csrf-token

<meta content="/t/IoUQxKVEL+KR2/HsnxTKmnALUA99jIr/LvjlgPKs=" name="csrf-token" />
Sign in
curl -s -v --data "session[email]=asdf@asdf.com;session[password]=123456" 
--data-urlencode "authenticity_token=/t/IoUQxKVEL+KR2/HsnxTKmnALUA99jIr/LvjlgPKs=" 
-b hello_cookies -c cookies 
http://localhost:3000/sessions > /dev/null

> POST /sessions HTTP/1.1
< HTTP/1.1 302 Found
< Location: http://localhost:3000/users/1
Successful access to restricted area
curl -s -v http://localhost:3000/users/1/edit -b cookies > /dev/null
> GET /users/1/edit HTTP/1.1
< HTTP/1.1 200 OK
Browser tools
●
●
●
●

console
render helpers
debug info
etc
rack-webconsole
>> User.find 1
=> #<User id: 1, name: "Alexander", email: "asdf@asdf.com", created_at: "2013-11-17 16:19:07",
updated_at: "2013-11-27 21:52:06", password_digest:
"$2a$10$MEICr2zekeBhh9HYCMLmXut3ckOsiL0TkksFWVX4asFf...", remember_token:
"cda4da34a5ee4238ddb78f20d4ec7e52b59fab4e", admin: nil>
>> helper
=> Error: undefined local variable or method `helper' for #<Rack::Webconsole::Sandbox:0x000000089cf600>
>> app
=> Error: undefined local variable or method `app' for #<Rack::Webconsole::Sandbox:0x000000089cf600>
>> Rails.root
=> #<Pathname:*/sample_app_rails_4>
>> self
=> #<Rack::Webconsole::Sandbox:0x000000089cf600 @locals={:u=>#<User id: 1, name: "Alexander"
rack-webconsole

`

- activate
Rails Panel
rails-footnotes: Assigns
rails-footnotes: DB
rails-footnotes: disable
?footnotes=false
xray-rails
Ctrl+Shift+X
better_errors 1
better_errors 2
exception_notifier
Provides a set of notifiers for sending
notifications when errors occur in a Rack/Rails
application
letter_opener
Preview email in the browser instead of
sending it
exception_notifier + letter_opener
Chrome: Form Editor
Chrome: JunkFill
Chrome: Sight
API calls, sight
hurl.it: params
hurl.it: response
POSTMAN
Chrome: REST console
Chrome: Advanced Rest Client
ВСЁ

More Related Content

What's hot

Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
 
Ror Seminar With agilebd.org on 23 Jan09
Ror Seminar With agilebd.org on 23 Jan09Ror Seminar With agilebd.org on 23 Jan09
Ror Seminar With agilebd.org on 23 Jan09Shaer Hassan
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleRaimonds Simanovskis
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby CoreHiroshi SHIBATA
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyLaunchAny
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsManoj Kumar
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesRaimonds Simanovskis
 
Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012alexismidon
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientAdam Wiggins
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsRaimonds Simanovskis
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015Fernando Hamasaki de Amorim
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Racksickill
 

What's hot (20)

Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 
Ror Seminar With agilebd.org on 23 Jan09
Ror Seminar With agilebd.org on 23 Jan09Ror Seminar With agilebd.org on 23 Jan09
Ror Seminar With agilebd.org on 23 Jan09
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
 
Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Ugo Cei Presentation
Ugo Cei PresentationUgo Cei Presentation
Ugo Cei Presentation
 

Similar to Debugging on rails

Background Jobs - Com BackgrounDRb
Background Jobs - Com BackgrounDRbBackground Jobs - Com BackgrounDRb
Background Jobs - Com BackgrounDRbJuan Maiz
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonManageIQ
 
A Z Introduction To Ruby On Rails
A Z Introduction To Ruby On RailsA Z Introduction To Ruby On Rails
A Z Introduction To Ruby On Railsrailsconf
 
Rails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiRails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiPivorak MeetUp
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Pedro Cunha
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Plataformatec
 
Otimizando Aplicações em Rails
Otimizando Aplicações em RailsOtimizando Aplicações em Rails
Otimizando Aplicações em RailsJuan Maiz
 
Rails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowRails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowChris Oliver
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Clinton Dreisbach
 
Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amfrailsconf
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyNikhil Mungel
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 

Similar to Debugging on rails (20)

Background Jobs - Com BackgrounDRb
Background Jobs - Com BackgrounDRbBackground Jobs - Com BackgrounDRb
Background Jobs - Com BackgrounDRb
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
A-Z Intro To Rails
A-Z Intro To RailsA-Z Intro To Rails
A-Z Intro To Rails
 
A Z Introduction To Ruby On Rails
A Z Introduction To Ruby On RailsA Z Introduction To Ruby On Rails
A Z Introduction To Ruby On Rails
 
Rails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiRails MVC by Sergiy Koshovyi
Rails MVC by Sergiy Koshovyi
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Laravel tips-2019-04
Laravel tips-2019-04Laravel tips-2019-04
Laravel tips-2019-04
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
 
Otimizando Aplicações em Rails
Otimizando Aplicações em RailsOtimizando Aplicações em Rails
Otimizando Aplicações em Rails
 
Rails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowRails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not Know
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
Integrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby AmfIntegrating Flex And Rails With Ruby Amf
Integrating Flex And Rails With Ruby Amf
 
Flex With Rubyamf
Flex With RubyamfFlex With Rubyamf
Flex With Rubyamf
 
Ruby meetup-dry
Ruby meetup-dryRuby meetup-dry
Ruby meetup-dry
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 

Recently uploaded

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 

Recently uploaded (20)

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 

Debugging on rails

  • 1. kiev.rb #2 #2 .rb kiev Debugging on Rails Mykhaylo Sorochan
  • 3. Debugged application Sample app for the Ruby on Rails Tutorial (Rails 4) https://github.com/railstutorial/sample_app_rails_4
  • 4. debugger gem 'debugger' debugger - call debugger config - .rdebugrc
  • 5. Debug location UserController#show def show @user = User.find(params[:id]) debugger @microposts = @user.microposts.paginate(page: params[:page]) end
  • 6. Debugger commands (rdb:9) help ruby-debug help v1.6.2 Type 'help <command-name>' for help on a specific command Available commands: backtrace delete enable help list pry restart source undisplay break disable eval info method ps save start up catch display exit irb next putl set step var condition down finish jump p quit show thread where continue edit frame kill pp reload skip trace
  • 7. Program info (rdb:4) help info Generic command for showing things about the program being debugged. -List of info subcommands: -info args -- Argument variables of current stack frame info breakpoints -- Status of user-settable breakpoints info catch -- Exceptions that can be caught in the current stack frame info display -- Expressions to display when program stops info file -- Info about a particular file read in info files -- File names and timestamps of files read in info global_variables -- Global variables info instance_variables -- Instance variables of the current stack frame info line -- Line number and file name of current position in source file info locals -- Local variables of the current stack frame info program -- Execution status of the program info stack -- Backtrace of the stack info thread -- List info about thread NUM info threads -- information of currently-known threads info variables -- Local and instance variables of the current stack frame
  • 8. Listing (rdb:1) help list l[ist] list forward l[ist] - list backward l[ist] = list current line l[ist] nn-mm list given lines NOTE - to turn on autolist, use 'set autolist' -> .rdebugrc
  • 9. Listing: in debug 12 @user = User.find(params[:id]) 13 debugger => 14 15 16 @microposts = @user.microposts.paginate(page: params[:page]) end
  • 10. Listing: l 23,25 l 23,25 [23, 25] in */sample_app_rails_4/app/controllers/users_controller.rb 23 if @user.save 24 sign_in @user 25 flash[:success] = "Welcome to the Sample App!"
  • 11. Breakpoints (rdb:4) help break b[reak] file:line [if expr] b[reak] class(.|#)method [if expr] set breakpoint to some position, (optionally) if expr == true (rdb:4) help delete del[ete][ nnn...] delete some or all breakpoints
  • 12. Set breakpoint (rdb:4) b ApplicationHelper#full_title Breakpoint 1 at ApplicationHelper::full_title (rdb:4) b 18 Breakpoint 2 file */sample_app_rails_4/app/controllers/users_controller.rb, line 18 (rdb:4) info b Num Enb What 1 y at ApplicationHelper:full_title 2 y at */sample_app_rails_4/app/controllers/users_controller.rb:18
  • 13. Navigate (rdb:4) help step s[tep][+-]?[ nnn] step (into methods) once or nnn times '+' forces to move to another line. '-' is the opposite of '+' and disables the force_stepping setting. (rdb:4) help next n[ext][+-]?[ nnn] step over once or nnn times, '+' forces to move to another line. '-' is the opposite of '+' and disables the force_stepping setting. (rdb:4) help up up[count] move to higher frame
  • 14. Stop at breakpoint (rdb:4) c Breakpoint 1 at ApplicationHelper:full_title [-1, 8] in */sample_app_rails_4/app/helpers/application_helper.rb 1 module ApplicationHelper 2 3 => 4 5 # Returns the full title on a per-page basis. def full_title(page_title) base_title = "Ruby on Rails Tutorial Sample App"
  • 15. Display (rdb:4) help display disp[lay] <expression> add expression into display expression list disp[lay] display expression list (rdb:4) help undisplay undisp[lay][ nnn] Cancel some expressions to be displayed when program stops.
  • 16. Display configured 4 => 5 6 def full_title(page_title) base_title = "Ruby on Rails Tutorial Sample App" if page_title.empty? (rdb:4) disp 2: controller_name = users 3: base_title =
  • 17. Display changed (rdb:4) n */sample_app_rails_4/app/helpers/application_helper.rb:6 if page_title.empty? 2: controller_name = users 3: base_title = Ruby on Rails Tutorial Sample App [1, 10] in */sample_app_rails_4/app/helpers/application_helper.rb 5 => 6 7 base_title = "Ruby on Rails Tutorial Sample App" if page_title.empty? base_title
  • 18. Conditional breakpoint (rdb:8) b ApplicationHelper#full_title if page_title=="Alexander" Breakpoint 4 at ApplicationHelper::full_title (rdb:8) c Breakpoint 1 at ApplicationHelper:full_title
  • 19. Variables (rdb:8) help var v[ar] cl[ass] show class variables of self v[ar] co[nst] <object> show constants of object v[ar] g[lobal] show global variables v[ar] i[nstance] <object> show instance variables of object. You may pass object id's hex as well. v[ar] l[ocal] show local variables
  • 20. Show variables 12 @user = User.find(params[:id]) 13 debugger => 14 15 @microposts = @user.microposts.paginate(page: params[:page]) end 16 17 def new (rdb:12) v i @_action_has_layout = true @_action_name = "show" @_config = {} @_env = {"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/users/1", "QUERY_STRING"=>"",... @_headers = {"Content-Type"=>"text/html"} @_lookup_context = #<ActionView::LookupContext:0x00000008e4b710 @details_key=nil, @details={:loc... @_params = {"action"=>"show", "controller"=>"users", "id"=>"1"} @_prefixes = ["users", "application"] @_request = #<ActionDispatch::Request:0x00000008e4bad0 @env={"GATEWAY_INTERFACE"=>"CGI/1.... @_response = #<ActionDispatch::Response:0x00000008e4baa8 @mon_owner=nil, @mon_count=0, @mo... @_response_body = nil @_routes = nil @_status = 200 @user = #<User id: 1, name: "Alexander", email: "asdf@asdf.com", created_at: "2013-11...
  • 21. Remote debugger Server Debugger.wait_connection = true Debugger.start_remote Client # rdebug --client -h 127.0.0.1 Connected. */sample_app_rails_4/app/controllers/users_controller.rb:14 @microposts = @user.microposts.paginate(page: params[:page]) [9, 18] in */sample_app_rails_4/app/controllers/users_controller.rb 9 end 10 11 def show 12 @user = User.find(params[:id]) 13 debugger => 14 @microposts = @user.microposts.paginate(page: params[:page])
  • 24. pry-debugger Debugger commands inside pry: step, next, continue, breakpoints
  • 25. jazz_hands jazz_hands is an opinionated set of consolerelated gems and a bit of glue: pry, awesome_print, hirb, pry-rails, pry-doc, pry-git, pry-remote, pry-debugger, pry-stack_explorer, coolline, coderay
  • 30. Logging ActiveSupport::Logger is used for logging Rails.root/log/[environment_name].log
  • 31. Log levels Rails.logger.level | name | level | |----------+-------| | :debug | 0 | | :info | 1 | | :warn | 2 | | :error | 3 | | :fatal | 4 | | :unknown | 5 | development, testing: production: log_level = 0 (:debug) log_level = 1 Messages with equal or higher level are sent to log
  • 32. Write to log logger.debug User.inspect logger.info user.id logger.fatal "Help!"
  • 33. Tagging log messages logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT)) logger.tagged("USER") { logger.info "hello" } => [USER] hello
  • 34. Tagged logging def show @user = User.find(params[:id]) logger.tagged("USER") { logger.info @user.email } # tail -f log/development.log|grep [USER] [USER] asdf@asdf.com
  • 35. Global variables for tracing __FILE__ - file name __LINE__ - line number
  • 36. Some useful CLI commands tail -n 100 tail -f grep, less
  • 37. Querying logs # cat log/development.log|grep GET|tail -n 2 Started GET "/assets/users.js?body=1" for 127.0.0.1 at 2013-11-21 23:32:01 +0200 Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2013-11-21 23:32:01 +0200 # cat log/development.log|grep GET|wc -l 574
  • 38. config.log_formatter Defines the formatter of the Rails logger. Defaults to ActiveSupport::Logger::SimpleFormatter production defaults to for all modes, Logger::Formatter. module ActiveSupport class Logger < ::Logger # Simple formatter which only displays the message. class SimpleFormatter < ::Logger::Formatter # This method is invoked when a log event occurs def call(severity, timestamp, progname, msg) "#{String === msg ? msg : msg.inspect}n" end end
  • 39. config.log_level Defaults to :debug for all modes, production defaults to :info.
  • 40. config.log_tags See ActionDispatch::Request methods. config.log_tags = [ :fullpath ] [/users/1] Started GET "/users/1" for 127.0.0.1 at 2013-11-... [/users/1] ActiveRecord::SchemaMigration Load (0.1ms) SELECT ... [/assets/application.css?body=1] Started GET "/assets/application.css?body=1" for 127...
  • 41. config.logger Accepts a logger conforming to the interface of Log4r or the default Ruby Logger class. Defaults to ActiveSupport::Logger, with auto flushing off in production mode.
  • 42. Rails console rails c rails c --sandbox irb pry
  • 43. rake routes > all_routes = Rails.application.routes.routes > require 'action_dispatch/routing/inspector' > inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
  • 44. All routes > puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new) Prefix Verb URI Pattern Controller#Action following_user GET /users/:id/following(.:format) users#following followers_user GET /users/:id/followers(.:format) users#followers users GET /users(.:format) users#index /users(.:format) users#create /users/new(.:format) users#new /users/:id/edit(.:format) users#edit /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update POST new_user GET edit_user GET user GET DELETE /users/:id(.:format) sessions POST new_session GET /sessions(.:format) sessions#create /sessions/new(.:format) sessions#new session DELETE /sessions/:id(.:format) microposts POST /microposts(.:format) micropost DELETE /microposts/:id(.:format) relationships POST /relationships(.:format) relationship DELETE /relationships/:id(.:format) root GET signup GET users#destroy sessions#destroy microposts#create microposts#destroy relationships#create relationships#destroy / static_pages#home /signup(.:format) users#new
  • 45. Routes for controller > puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, 'microposts') Prefix Verb microposts POST URI Pattern Controller#Action /microposts(.:format) microposts#create micropost DELETE /microposts/:id(.:format) microposts#destroy
  • 46. Filtering routes: GET > puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, 'users').lines.grep(/GET/).join following_user GET /users/:id/following(.:format) users#following followers_user GET /users/:id/followers(.:format) users#followers users GET new_user GET edit_user GET user GET signup GET /users(.:format) users#index /users/new(.:format) users#new /users/:id/edit(.:format) users#edit /users/:id(.:format) users#show /signup(.:format) users#new
  • 47. Filtering routes: /relation/ > puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new).lines.grep(/relation/).join relationships POST /relationships(.:format) relationship DELETE /relationships/:id(.:format) relationships#create relationships#destroy
  • 48. Matching routes > r = Rails.application.routes > r.recognize_path "/users/47" => {:action=>"show", :controller=>"users", :id=>"47"} > r.recognize_path "/users/87", :method => "PUT" => {:action=>"update", :controller=>"users", :id=>"87"} > r.recognize_path "/users/47.json" => {:action=>"show", :controller=>"users", :id=>"47", :format=>"json"}
  • 49. Named routes > app.users_path => "/users" > app.users_path(:json) => "/users.json" > app.user_path(1) => "/users/1" > app.user_path(1, :xml) => "/users/1.xml" > app.user_path(1, :count => 4) => "/users/1?count=4"
  • 50. Making requests > app => #<ActionDispatch::Integration::Session:...> > app.reset!
  • 51. Get requests > app.get '/users/1/edit' Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:24:18 +0200 Processing by UsersController#edit as HTML Parameters: {"id"=>"1"} Redirected to http://localhost:3000/signin Filter chain halted as :signed_in_user rendered or redirected Completed 302 Found in 3ms (ActiveRecord: 0.4ms) > app.response.body => "<html><body>You are being <a href="http://localhost:3000/signin">redirected</a>.</body></html>" > app.get_via_redirect '/users/1/edit' Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:26:44 +0200 Redirected to http://localhost:3000/signin ... Started GET "/signin" for 127.0.0.1 at 2013-11-26 23:26:44 +0200
  • 52. Session cookies > app.cookies => #<Rack::Test::CookieJar... > app.cookies.to_hash => {"_sample_app_session"=>"RC9j... app.cookies - received/sent cookies
  • 53. Post requests: signin > app.response.body.lines.grep /csrf-token/ => ["<meta content="n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=" name="csrf-token" />n"] > app.post '/sessions', :authenticity_token => 'n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=', 'session[email]' => 'asdf@asdf.com', 'session[password]' => '123456' Started POST "/sessions" for 127.0.0.1 at 2013-11-26 23:33:01 +0200 Processing by SessionsController#create as HTML Parameters: {"authenticity_token"=>"n+9uCcG2JJmgwhnNcp4s9jTwOU55RAPOdtAHWstcpKQ=", "session"=>{"email" =>"asdf@asdf.com", "password"=>"[FILTERED]"}} Redirected to http://localhost:3000/users/1/edit Completed 302 Found in 281ms (ActiveRecord: 7.2ms) app.post_via_redirect
  • 54. Access to restricted resource > app.get '/users/1/edit' Started GET "/users/1/edit" for 127.0.0.1 at 2013-11-26 23:38:47 +0200 Processing by UsersController#edit as HTML Completed 200 OK in 41ms (Views: 35.7ms | ActiveRecord: 0.8ms)
  • 55. Call helper > helper => #<ActionView::Base:... > # ApplicationHelper#full_title > helper.full_title "Sign Up" => "Ruby on Rails Tutorial Sample App | Sign Up"
  • 56. Call helper with cookie > def cookies; @cookies ||= HashWithIndifferentAccess.new(app.cookies.to_hash); end > helper.current_user => #<User id: 1, name: ....
  • 57. ActiveRecord logging > ActiveRecord::Base.logger = Logger.new(STDOUT) > ActiveRecord::Base.clear_active_connections! > # reload! > User.find 1 D, [2013-12-30T21:55:17.775769 #24810] DEBUG -- : WHERE "users"."id" = ? LIMIT 1 [["id", 1]] => #<User id: 1, name: "hello",.... User Load (0.2ms) SELECT "users".* FROM "users"
  • 58. ActiveRecord hide logging > ActiveRecord::Base.logger = Logger.new(nil) > ActiveRecord::Base.clear_active_connections! > # reload! > User.find 1 => #<User id: 1, name: "hello",....
  • 59. Raw SQL requests > ActiveRecord::Base.connection.select_all("select * from users") => #<ActiveRecord::Result:... > puts _ {"id"=>1, "name"=>"hello", "email"=>"hello@hello.com", "created_at"=>"2013-....
  • 60. .irbrc Save your helper methods ● routes ● sql logging ● etc
  • 61. CLI tools Making HTTP requests with curl ● ● ● ● ● ● -s silent -v verbose -c save cookie -b use cookie -data POST data -data-urlencode URL-encode POST data
  • 62. Access restricted area curl -s -v http://localhost:3000/users/1/edit > /dev/null > GET /users/1/edit HTTP/1.1 < HTTP/1.1 302 Found < Location: http://localhost:3000/signin
  • 63. Visit /signin, get token curl -s -c hello_cookies http://localhost:3000/signin > /dev/null |grep csrf-token <meta content="/t/IoUQxKVEL+KR2/HsnxTKmnALUA99jIr/LvjlgPKs=" name="csrf-token" />
  • 64. Sign in curl -s -v --data "session[email]=asdf@asdf.com;session[password]=123456" --data-urlencode "authenticity_token=/t/IoUQxKVEL+KR2/HsnxTKmnALUA99jIr/LvjlgPKs=" -b hello_cookies -c cookies http://localhost:3000/sessions > /dev/null > POST /sessions HTTP/1.1 < HTTP/1.1 302 Found < Location: http://localhost:3000/users/1
  • 65. Successful access to restricted area curl -s -v http://localhost:3000/users/1/edit -b cookies > /dev/null > GET /users/1/edit HTTP/1.1 < HTTP/1.1 200 OK
  • 67. rack-webconsole >> User.find 1 => #<User id: 1, name: "Alexander", email: "asdf@asdf.com", created_at: "2013-11-17 16:19:07", updated_at: "2013-11-27 21:52:06", password_digest: "$2a$10$MEICr2zekeBhh9HYCMLmXut3ckOsiL0TkksFWVX4asFf...", remember_token: "cda4da34a5ee4238ddb78f20d4ec7e52b59fab4e", admin: nil> >> helper => Error: undefined local variable or method `helper' for #<Rack::Webconsole::Sandbox:0x000000089cf600> >> app => Error: undefined local variable or method `app' for #<Rack::Webconsole::Sandbox:0x000000089cf600> >> Rails.root => #<Pathname:*/sample_app_rails_4> >> self => #<Rack::Webconsole::Sandbox:0x000000089cf600 @locals={:u=>#<User id: 1, name: "Alexander"
  • 76. exception_notifier Provides a set of notifiers for sending notifications when errors occur in a Rack/Rails application
  • 77. letter_opener Preview email in the browser instead of sending it