In-depth HTTP traffic analysis using tcpdump & Wireshark
From time to time we're convinced that an error must be very close to the network card, OS IP stack or compiler. In reality this is quite rare, so before continuing, triple-check that the issue is not located between chair and keyboard...
If you're still convinced that a in-depth analysis of network traffic might help you, go on:
-
Find out the IP address the client causing trouble will come from.
-
Replace 147.0.0.123 with the client address, log into your web server and run:
`remote$ sudo tcpdump host 147.0.0.123 and port 80 -s 0 -w...
Don't mix Array#join and String#html_safe
You cannot use Array#join
on an array of strings where some strings are html_safe
and others are not. The result will be an unsafe string and will thus be escaped when rendered in a view:
unsafe_string = '<span>foo</span>'
safe_string = '<span>bar</span>'.html_safe
[unsafe_string, safe_string].join(' ') # will incorrectly render as '<span>foo</span><span&t;bar</span>'
Bad
The solution is not to call html_safe
on the joined array and if you thought it would be, you [don't understand how XSS prot...
Styling and scaling for mobile devices
If you want your application to display properly on iPad, iPhone or Android there are two things to do:
Define a stylesheet for mobile devices
Using the media
attribute on stylesheet
HTML tags allows you to have a CSS for mobile browsers:
<!--[if !IE]><!-->
<%= stylesheet_link_tag 'mobile', :media => 'only screen and (max-device-width: 1024px)' %>
<!--<![endif]-->
Here I chose 1024 pixels as the maximum device width to include the iPad. If you want to target only mobile phones, pick 960 to include high-end Android d...
Computational cost of SSL connections
In January this year (2010), Gmail switched to using HTTPS for everything by default. Previously it had been introduced as an option, but now all of our users use HTTPS to secure their email between their browsers and Google, all the time. In order to do this we had to deploy no additional machines and no special hardware. On our production frontend machines, SSL/TLS accounts for less than 1% of the CPU load, less than 10KB of memory per connection and less than 2% of network overhead. Many people believe that SSL takes a lot of CPU time and...
Firefox: Remove dotted border from focused buttons
The following Sass will do the trick:
button,
input[type="reset"],
input[type="button"],
input[type="submit"],
input[type="file"] > input[type="button"]
&::-moz-focus-inner
border: none
There's also a plain CSS version.
Note that you can no longer visually navigate through a form with the keyboard without these borders.
Cucumber steps to test input fields for equality (with wildcard support)
Our collection of the most useful Cucumber steps, Spreewald, now supports exact matching of form fields and lets you use wildcards.
Examples:
And the "Money" field should contain "134"
# -> Only is green if that field contains the exact string "134", neither "134,50" nor "1000134"
And the "Name" field should contain "*Peter*"
# -> Accepts if the field contains "Peter" or "Anton Peter" or "Peter Schödl" etc.
And the "Comment" field should contain "Dear*bye"
# -> Accepts if the field contains "De...
Inspect the page content in a Cucumber session
When you need to see the content of a page (i.e. not all the HTML but the relevant text body)
- you can do
pp (html_content)
- pp will format the html String human readable pretty printed
- where html_content can be replaced by one of the following commands:
Rails
body
or response.body
Capybara:
page.driver.html.content
page.body
Webrat:
Nokogiri::HTML(response.body).content
The returned strings can be cleaned up by calling .gsub(/^\s*$/, '').squeeze("\n")
on them.\
Although this may be useful for d...
Check if a field or button is disabled with Cucumber
Using this step definition you can check if any form field (text field, checkbox, etc) or button is disabled:
Then the "Name" field should be disabled
And the "Save" button should be disabled
But the "Locked" field should not be disabled
Capybara
This step part of Spreewald.
Webrat
Then /^"([^\"]*)" should( not)? be disabled$/ do |label, negate|
attributes = field_labeled(label).element.attributes.keys
attributes.send(negate ? :should_not : :should...
Encode or decode HTML entities
Use the htmlentities gem.
Encoding works like this:
require 'htmlentities'
coder = HTMLEntities.new
string = "<élan>"
coder.encode(string) # => "<élan>"
coder.encode(string, :named) # => "<élan>"
coder.encode(string, :decimal) # => "<élan>"
coder.encode(string, :hexadecimal) # => "<élan>"
Decoding works like this:
require 'htmlentities'
coder = HTMLEntities.new
string = "élan"
cod...
Virtual attributes for array fields
When a has_many
association basically serves to store a list of associated strings (tags, categories, ...), it can be convenient to represent this association as a string array in the containing model. Here is an example for this pattern from the acts-as-taggable-on gem:
post = Post.last
p post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
p post.tag_list # ['bam']
This string array tag_list
is magical in several ways:
- It is read from and written to a `has...
Virtual attributes for integer fields
Note that this card is very old. You might want to use ActiveType for your auto-coerced virtual attributes instead.
We sometimes give our models virtual attributes for values that don't need to be stored permanently.
When such a virtual attribute should contain integer values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that...
Manipulate an array attribute using multiple check boxes
E.g. when you're using a tagging gem, you have seen virtual attributes that get and set a string array:
post = Post.last
puts post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
puts post.tag_list # ['bam']
If you would like to create a form displaying one check box per tag, you can do this:
- form_for @post do |form|
= form.check_box :tag_list, { :multiple => true }, 'foo', nil
= form.check_box :tag_list, { :multiple => true }, 'bar', nil
=...
Test that a select option is selected with Cucumber
This step tests whether a given select option comes preselected in the HTML. There is another step to test that an option is available at all.
Capybara
Then /^"([^"]*)" should be selected for "([^"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
with_scope(selector) do
field_labeled(field).find(:xpath, ".//option[@selected = 'selected'][text() = '#{value}']").should be_present
end
end
Webrat
...
Useful collection of Sass mixins
This collection of Sass mixins enables cross-browser styling (including IE with CSS3PIE) with less lines of code.
This enables PIE for IE up to version 8 only (the first part is not possible in Haml, so use ERB):
<!--[if !IE]><!-->
<%= stylesheet_link_tag 'screen', :media => 'screen' %>
<!--<![endif]-->
<!--[if lte IE 8]>
<%= stylesheet_link_tag 'screen_with_pie', :media => 'screen' %>
<![endif]-->
These would be your two screen Sasses:
# screen_with_pie.sass
...
Problems with Rails 3 Remote Links and Forms Using jQuery .live() in IE
There is a problem with AJAX response handling for Rails 3 remote links and forms in Internet Explorer. This problem affects applications still using jQuery 1.4.2.
Aliases for routes
The following initializer provides an :alias => "my_route_name"
option to restful routes in your route.rb
. This simply makes the same route also available under a different ..._path / ..._url helpers.
For example,
map.resources :notes, :alias => :snippets
Gives you
notes_path, notes_url, new_note_path... #as always
snippets_path, snippets_url, new_snippet_path... #from the alias
Put this into an initializer:
Git: "Interactive reverts"
If you need to revert only parts of one or several commits the following workflow can help:
If you need to revert multiple changes, make a branch and squash it afterwards.
For every commit you need to revert, starting at the most recent, do:
git revert -n [COMMIT] #revert, but don't automatically commit
... #fix any conflicts
git reset #unstage all changes
git add -p #this will ask you for every change, whethe...
Generate a Unicode nonbreaking space in Ruby
Regular spaces and non-breaking spaces are hard to distinguish for a human.
Instead of using the
HTML entity or code like " " # this is an nbsp
, use a well-named helper method instead.
def nbsp
[160].pack('U*')
end
160 is the ASCII character code of a non-breaking space.
Rails 3 Remote Links and Forms: A Definitive Guide
Thanks to habits engrained by Rails 2’s link_to_remote and remote_form_for, we expect that Rails 3 would also handle the AJAX response for our remote links and forms. But it doesn’t; it leaves that for you.
Request a non-HTML format in controller specs
If a controller action responds to other formats than HTML (XML, PDF, Excel, JSON, ...), you can reach that code in a controller spec like this:
describe UsersController do
describe '#index' do
it 'should be able to send an excel file' do
# stubs and expectations go here
get :index, :format => 'xls'
end
end
end
Remember that both the :format
parameter and the HTTP_ACCEPT
header can m...
Get the current layout's name in a view or partial
This returns the name (including path) of your current layout:
response.layout
=> "layouts/admin" # inside views that are using the 'admin' layout
You most likely do not need the full path, so go ahead and do this:
File.basename(response.layout)
=> "admin"
Use form_for without the enclosing form tag
In rare cases you might need something like form_for
(for using form builder methods on the resulting block element) but without the surrounding form. One such case would be updating some of a form's fields via XHR.
You can simply use Rails' fields_for
to do things like this in your views (HAML here):
- fields_for @user do |form|
= form.label :email, 'E-Mail'
= form.text_field :email
You will only receive the form content you gave, no hidden inputs incl...
Generate a path or URL string from an array of route components
When using form_for
you can give the form's target URL either as a string or an array:
form_for(admin_user_path(@user)) do ... end
# same as:
form_for([:admin, @user]) do ... end
Same for link_to:
link_to("Label", edit_admin_user_path(@user))
# same as
link_to("Label", [:edit, :admin, @user])
polymorphic_path
and polymorphic_url
If you would like to generate a path or URL string from an array of route components just as form_for
does, you can use polymorphic_path
or polymorphic_url
:
polymorphic...
Match strings in a given order with Cucumber and Capybara
Sometimes the order in which strings appear on a page matters to you.
Spreewald gives you steps like these:
Then I should see in this order:
| Alpha Group |
| Augsburg |
| Berlin |
| Beta Group |
Or, if you prefer multiline strings:
Then I should see in this order:
"""
Alpha Group
Augsburg
Berlin
Beta Group
"""
The step ignores all HTML tags and only tests on plain text.