Spec "content_for" calls in helpers
This only applies to RSpec below version 1.3.2. The issue has been fixed in RSpec 1.3.2, and most likely RSpec 2 and later versions.
When you have a helper that calls content_for
and want to check its behavior you should probably write a feature instead. If you still want to do it, mind the following.
Consider this helper:
module LayoutHelper
def title(string)
content_for :title, string
string
end
end
Somewhere in the layout we'd then say something like this: `<%= yield :title %...
ActiveRecord: When aggregating nested children, always exclude children marked for destruction
When your model is using a callback like before_save
or before_validation
to calculate an aggregated value from its children, it needs to skip those children that are #marked_for_destruction?
. Otherwise you will include children that have been ticked for deletion in a nested form.
Wrong way
class Invoice < ApplicationRecord
has_many :invoice_items
accepts_nested_attributes_for :invoice_items, :allow_destroy => true # the critical code 1/2
before_save :calculate_and_store_amount # the crit...
What collapsing margins are, how they work and when margins do not collapse
Imagine you have 2 HTML boxes. The first one has a margin-bottom
of let's say 30px
and the second one a margin-top
of 20px
. After rules of collapsing margins have been applied we have a margin of 30px
(not 50px
) between these two boxes . This is because no addition of both margins takes place but the maximum of both is applied. This behavior is called collapsing margins.
Oftentimes it is a good behavior but collapsing margins can be annoying, too. For example child el...
RestClient sends XML Accept header by default
REST Client is a nice, simple HTTP client library for Ruby.
When you do a simple GET request like that:
RestClient.get 'http://example.com/'
it will result in this request beeing sent to www.example.com:
GET / HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Host: www.example.com
The application/xml
accept header might lead to unexpected results on your server. You can force REST Client to ask the server for default text/html
that way:
RestC...
Auto-generate Cucumber navigation paths
Don't you just hate to write Cucumber path helpers to be able to say this?
When I go to the user form for "foo@bar.de" # goes to edit_user_path(User.find_by_anything!('foo@bar.de'))
When I go to the form for the user "foo@bar.de" # goes to edit_user_path(User.find_by_anything!('foo@bar.de'))
When I go to the form for the user above" # goes to edit_user_path(User.last)
When I go to the project page for "World Domination" # goes to project_path(Project.find_by_anything!('World Domination')
...
High-level Javascript frameworks: Backbone vs. Ember vs. Knockout
This is a very general introduction to MV* Javascript frameworks. This card won't tell you anything new if you are already familiar with the products mentioned in the title.
As web applications move farther into the client, Javascript frameworks have sprung up that operate on a higher level of abstraction than DOM manipulation frameworks like jQuery and Prototype. Such high-level frameworks typically offer support for client-side view rendering, routing, data bindings, etc. This is useful, and when you write a moderately complex Javascript ...
How to overwrite and reset constants within Cucumber features
In order to save the original value of a constant, set the new value and restore the old value after a scenario was completed, you can use the following helper. It takes care of saving the old constant value, setting the new one without throwing warnings and resets the value with an After
hook.
This module also enables you to introduce new global constants.
Since these newly defined constants do not have any value to be reset to,
they simply are deleted (remove_const
) once the respective Cucumber step finishes.
You can copy the file at...
Cucumber step to test that a tooltip text exists in the HTML
Tooltips that are delivered through HTML attributes are encoded. Decode entities before checking for their presence.
Capybara:
Then /^there should( not)? be a(n encoded)? tooltip "([^"]*)"$/ do |negate, encoded, tooltip|
tooltip = HTMLEntities.new.encode(tooltip) if encoded
Then "I should#{negate} see \"#{tooltip}\" in the HTML"
end
Note
This step uses the htmlentities gem described in another card.
Ma...
nruth/show_me_the_cookies - GitHub
Some helpers for poking around at your Capybara driven browser's cookies in integration tests.
Supports Capybara's bundled drivers (rack-test, Selenium Webdriver), and adapters for other drivers may be added.
Flexible overflow handling with CSS and JavaScript
You can use text-overflow
to truncate a text using CSS but it does not fit fancy requirements.
Here is a hack for the special case where you want to truncate one of two strings in one line that can both vary in length, while fully keeping one of them. See this example screenshot where we never want to show an ellipsis for the distance:
![Flexible overflow with optional ellipsis](https://makandracards.com/makandra/5885-a-flexible-overflow-ellipsis/at...
Use CSS "text-overflow" to truncate long texts
When using Rails to truncate strings, you may end up with strings that are still too long for their container or are not as long as they could be. You can get a prettier result using stylesheets.
The CSS property text-overflow: ellipsis
has been around for quite a long time now but since Firefox did not support it for ages, you did not use it. Since Firefox 7 you can!
Note that this only works for single-line texts. If you want to truncate tests across multiple lines, use a JavaScript solution like...
Test whether a form field exists with Cucumber and Capybara
The step definition below lets you say:
Then I should see a field "Password"
But I should not see a field "Role"
Here is the step definition:
Then /^I should( not)? see a field "([^"]*)"$/ do |negate, name|
expectation = negate ? :should_not : :should
begin
field = find_field(name)
rescue Capybara::ElementNotFound
# In Capybara 0.4+ #find_field raises an error instead of returning nil
end
field.send(expectation, be_present)
end
Note that you might have to adapt the step defi...
Why your javascripts should be executed after the dom has been loaded
Most of the JavaScript snippets have code that manipulates the DOM. For that reason dom manipulating javascript code should have been executed after the DOM has loaded completely. That means when the browser has finished HTML parsing and built the DOM tree. At that time, you can manipualte the DOM although not all resources (like images) are fully loaded.
The following snippets show how you can do this with plain JavaScript, jquery or prototype ([dom ready ...
Enabling view rendering for controller specs
Views are normally (for good reason) not rendered in controller specs. If you need it to happen, use:
RSpec 1 (Rails 2):
RSpec 2 (Rails 3):
Note that you can't use that inside it
blocks but need to put it in the nesting example group, like this:
describe '#update' do
conte...
How to print Github wiki pages
I have no idea how it's supposed to work (or why the don't have a print CSS), but this works for pages written with Markdown:
- "Edit" the wiki page
- Copy all text
- Run a Markdown interpreter and pipe its result, e.g.:
kramdown > /tmp/github.html
- Paste your markdown
- Press Ctrl-D to finalize your input
- Open the generated HTML file and print it.
O_o
CSS box-shadow not working in IE9 inside tables with collapsing borders
Though Internet Explorer 9 supports the box-shadow
CSS property there is a nasty bug which sometimes prevents it from rendering the shadow properly.
Consider this HTML:
<table style="border-collapse: collapse">
<tr>
<td>
<div style="box-shadow: 0 0 10px #f00">Hello universe</div>
</td>
</tr>
</table>
While it works in other browsers, IE9 is not showing any shadow. For some reason, it requires border-collapse: separate
for the table to be set:
<table style="border-collapse: separate" c...
How to embed images in higher resolutions for printing
When you print out a HTML pages, all raster images (like PNGs) will appear aliased. This is because a printer's resolution is usually much higher than that of a computer screen.
If an image absolutely must look awesome when printed, a solution is to embed the image in much higher solution than needed (e.g. four times the horizontal resolution), then scale it down to the desired width using CSS.
Note that this will slightly alter the image's appearance on the screen because browsers will scale down the image [using an anti-aliasing method](...
Detect mobile or touch devices on both server and client
Although it's tempting flirt with detecting mobile/touch devices with CSS media queries or Javascript feature detection alone, this approach will be painful when heavily customizing a feature beyond just tweaking the looks. Eventually you will want want the same detection logic to be available on both server and client side.
This card shows how to get a Ruby method touch_device?
for your Rails views and a method TouchDevice.isPresent()
for your Javascripts.
Note that we are detecting touch devices by grepping the user agent, and the ke...
Fix AssociationTypeMismatch
When you're getting this error, one possibility is that you've created a select field for an association instead of the associated object's id. Example:
form.select :unit, Unit.for_select
will be expected to deliver a real Unit
object, whereas
form.select :unit_id, Unit.for_select
will make Rails typecast the String value from the select field to the unit's ID.
How to deal with MethodNotAllowed errors
One of the most common production errors are ActionController::MethodNotAllowed
errors. They usually happen when someone reloads a form by pressing enter
/return
in the URL field, or by opening JavaScript links incorrectly.
The attached initializer provides a default way to deal with this.
You'll get the following behaviour:
- if the incorrect request has a
HTTP_REFERER
coming from the same application, set a flash, and redirect back - if the incorrect request has no
HTTP_REFERER
or one coming from an external source, set a flash...
Re-enable submit buttons disabled by the :disable_with option
Submit buttons in Rails come with a useful option :disable_with
which will disable the button when clicked and change its label to something like "Please wait...".
An annoying side effect of that feature is that when you use the back button to return to the form, the submit button will be greyed out and disabled.
A solution is to re-enable the submit button before leaving the page. This works in Rails 3:
$(window).unload(function() {
$.rails.enableFormElements($($.rails.formSubmitSelector));
});
ERB templates and comments
When you use one line Ruby comments in ERB templates you should never do this (notice the whitespace in front of #
):
<% # my comment %>
<div>my html</div>
This leads to strange html output. To avoid long debugging sessions, you should never have a whitespace before the #
character (but newline is allowed)
<%# this works as expected %>
<%
# this works, too
# foo bar baz
%>
User friendly form design
There are two types of forms: User forms, e.g. for sign up, and Administration forms, to maintain data. They are quite different in purpose: The former must be simple and quick to fill in, whereas the latter should organize a lot of data in a reasonable way.
Guidelines
- Simple is win.
- Align forms vertically, one element below the other.
- Never explain your form. If it is too complicated, redesign.
- Skimp on lines and boxes. If you need them, something is wrong with your form.
A form element needs
- Label. Above the field i...
How to define a custom context menu within HTML (Firefox 8+)
Since Firefox 8 it is possible to define custom context menus (right clicking) with HTML markup.