The information in this card is only relevant for Rails 2.3-era apps.
This note gives a quick introduction into caching methods (page caching, action caching and fragment caching) in rails and describes some specific problems and solutions.
The descriptions below are valid for Rails 2 and 3. Recently, caching with timestamp- or content-based keys has become more popular which saves you the pain of invalidating stale caches.
To enable or disable caching in rails you ca...
Liquid Canvas is a JavaScript library which allows you to draw inside an HTML canvas element with an easy yet powerful description language.
It can be used to add graphics to your web page without ever touching an image creation tool such as The Gimp, Inkscape or Photoshop.
Check out the Demo and the basic example and then download version 0.3.
Note that you cannot currently use Ruby 1.9.2 with Rails 2 applications that use RSpec, so don't upgrade if that is your setup. The rspec-rails gem has a fatal bug that was only fixed for rspec-rails-2.x, which only supports Rails 3. There is no fix for the rspec-rails-1.3.x series of the gem which supports Rails 2.
Anyway, here are upgrade instructions if you only work with Rails 3 or don't use RSpec. You will lose all your gems in the process, but you can get them back easily if you h...
Sometimes you can make your life easier by not allowing a record attribute to be changed after the record was created. An example for this is when your model represents a child node in a composition and has logic that is hard to support for cases when the container changes.
Here is an example for a container Region
composed of many children of type Holiday
. After saving a Holiday
it caches the current number of holidays in its region:
class Region < ActiveRecord::Base
...
Specify these gem versions in your Gemfile:
gem 'cucumber', '~> 1.3.0'
gem 'cucumber-rails', '= 0.3.2' # max version for Rails 2
gem 'capybara', '< 2' # capybara 2+ requires Rails 3
gem 'mime-types', '< 2' # dependeny of capybara
gem 'nokogiri', '< 1.6' # dependency of capybara
gem 'rubyzip', '< 1' # dependency of selenium-webdriver, rubyzip 1+ requires Ruby 1.9
gem 'cucumber_factory'
gem 'database_cleaner', '< 1'
gem 'cucumber_spinner', '~> 0.2.5'
gem 'launchy', '~> 2.1.2'
With these versions set, `...
Sometimes you need to dynamically load an image and do something as soon as its loaded (when for example its size is already available).
With jQuery, this seems to work across browsers:
$('<img>')
.attr('src', '')
.load(function() {
alert('fully loaded!');
})
.attr('src', '/the/real/image/url');
The shell variable PS1
holds your bash prompt. You might want to change it to serve your needs best. Here is how to:
\[\e[
and \]
so your shell can correctly count its prompt's lengthIf in your application your users pass along params that result in filenames, like invoices/generated?number=123
. This could be your (very careless) controller method:
def generated
send_file File.join(Rails.root, 'shared', 'invoices', params[:number])
end
This allows your users not only to access those files but also any files your application can read, like this:
invoices/generated?number=../../../../../etc/passwd
# => send_file '/etc/passwd'
You do not want this. In most cases you should prefer a show
met...
Pie sometimes does not properly redraw elements upon changes. This often happens when the change comes from somewhere further up the DOM.
Consider something like:
<ul>
<li class="active"><div class="content">Active element</div></li>
<li class="inactive"><div class="content">Inactive element</div></li>
</ul>
with CSS
li .content {
-webkit-box-shadow: #666 0px 2px 3px;
-moz-box-shadow: #666 0px 2px 3px;
box-shadow: #666 0px 2px 3px;
behavior: url(/PIE.htc);
back...
The attached RSpec matcher exist_in_database
checks if a given record still exists in the database and has not been destroyed:
describe Ticket do
describe '.purge_expired' do
fresh_ticket = Ticket.create(:expiry => Date.tomorrow)
expired_ticket = Ticket.create(:expiry => Date.yesterday)
Ticket.purge_expired
fresh_ticket.should exist_in_database
expired_ticket.should_not exist_in_database
end
end
Note that there is also [ActiveRecord::Base#destroyed?
](http://apidock.com/rails/A...
We are maintaining some vintage projects with tests written in Test::Unit instead of RSpec. Mocks and stubs are not features of Test::Unit, but you can use the Mocha gem to add those facilities.
The following is a quick crash course to using mocks and stubs in Mocha, written for RSpec users:
|---------------------------------------------------------|
| RSpec | Mocha |
|---------------------------------------------------------|
| obj = double()
| obj = mock()
|
| obj.stub(:method => 'value')
| `obj.stubs...
If you have the following deprecation warning after upgrading to rails >= 2.3.10
DEPRECATION WARNING: The :overwrite_params option is deprecated. Specify all the necessary parameters instead.
that is for example caused by
url_for( :overwrite_params => { :order => 'name', :dir => 'asc' } )
you can fix this by using params.merge {:my_param_to_overwrite => 'foo' }
.
To fix the example above the code could look like:
url_for( params.merge { :order => 'name...
In order to
you can use RSpec's "nested" format. It looks like this:
Tool
validations
should require model to be set
should require place_id to be set
#identifier
should include the model and tag if the tool has a tag
should return the model if the tool has no tag
.search
should find tools by model and maker
should find tools by serial number
Call RSpec like...
You will occasionally need to clean out your database while keeping the schema intact, e.g. when someone inserted data in a migration or when you had to kill -9
a frozen test process.
Old Capybara versions already have the Database Cleaner gem as dependency. Otherwise add database_cleaner
to your *Gemfile`. This lets you say this from the Rails console:
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.cl...
When you click a link or a press a button on a Selenium-controlled browser, the call will return control to your test before the next page is loaded. This can lead to concurrency issues when a Cucumber step involves a Selenium action and a Ruby call which both change the same resources.
Take the following step which signs in a user through the browser UI and then sets a flag on the user that was just signed in:
Given /^the user "([^"]*)" signed in (\d) days ago$/ do |name, days|
visit new_session_path
fill_in 'Username', :w...
Adds a slide out panel to your Rails application that directs clients to test stories that have been marked as 'delivered' in Pivotal Tracker.
jQuery offers many different methods to move a selection through the DOM tree. These are the most important:
$element.find(selector)
Get the descendants of each element in the current set of matched elements, filtered by a selector. Does not find the current element, even it matches. If you wanted to do that, you need to write $element.find(selector).addBack(selector)
.
$element.closest(selector)
Get the first ancestor el...
When you set both a record's association and that association's foreign key attribute, Rails does not realize you are talking about the same thing. The association change will win in the next save
, even if the foreign key attribute was changed after the association.
As an example, assume you have these two models:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
validates_presence_of :group_id
belongs_to :group
end
We will now load a User
and change both its `g...
So you are comparing two Time
objects in an RSpec example, and they are not equal, although they look equal:
expected: Tue May 01 21:59:59 UTC 2007,
got: Tue May 01 21:59:59 UTC 2007 (using ==)
The reason for this is that Time
actually tracks fractions of a second, although #to_s
doesn't say so and even though you probably only care about seconds. This means that two consecutive calls of Time.now
probably return two inequal values.
Consider freezing time in your tests so it is not dependent on the speed of the executi...
In order to cover some edge cases you rarely care about, Range#include?
will become very slow in Ruby 1.9:
Range#include? behaviour has changed in ruby 1.9 for non-numeric ranges. Rather than a greater-than/less-than check against the min and max values, the range is iterated over from min until the test value is found (or max) [...] Ruby 1.9 introduces a new method Range#cover? that implements the old include? behaviour, however this method isn’t available in 1.8.7.
The attached ...
If you have content inside a page that is hidden by CSS, the following will work with Selenium, but not when using the Rack::Test driver. The Selenium driver correctly only considers text that is actually visible to a user.
Then I should not see "foobear"
This is because the Rack::Test driver does not know if an element is visible, and only looks at the DOM.
Spreewald offers steps to check that an element is hidden by CSS:
Then "foo" should be hidden
You can also check that an el...
If you want to get a deep understanding of how closures, blocks, procs & lambdas in Ruby work, check out the code at the attached link.
Here the summary:
^
---------------------------- Section 6: Summary ----------------------------
So, what's the final verdict on those 7 closure-like entities?
"return" returns from closure
True closure? or declaring context...? Arity check?
...
Although you can access many symbols using the AltGr key you may be missing some, like the en-dash (–) or em-dash (—). You can use a compose key for them instead.
First, make sure you have a compose key configured.
I suggest using the "Menu" key which is located between the right Meta and Ctrl key.
Control Center → Keyboard → Layout → Options → Position of Compos...
A while ago we were working on an application that had an entire version specially created for mobiles, such as the iPhone. This specific application was entirely tested with Capybara, Steak and Selenium Webdriver. Although the test suite wasn’t the fastest one in the world, the web application was very well tested, and to guarantee that we would also be testing the mobile version, we would have to simulate an iPhone user agent accessing the application.
But wait, you might be thinking that we are not able to change browser headers while ...