Note: For PostgreSQL you should use advisory locks. For MySQL we still recommend the solution in this card.
If you need to synchronize multiple rails processes, you need some shared resource that can be used as a mutex. One option is to simply use your existing (MySQL) database.
The attached code provides a database-based model level mutex for MySQL. You use it by simply calling
Lock.acquire('string to synchronize on') do
# non-th...
To test whether two arrays have the same elements regardless of order, you can use the =~
matcher in RSpec < 2.11:
actual_array.should =~ expected_array
If either side is an ActiveRecord scope rather than an array, you should call to_a
on it first, since =~
does not play nice with scopes:
actual_scope.to_a.should =~ expected_scope.to_a
If you use RSpec >= 2.11 we recommend using the match_array
or contain_exactly
matchers instead of =~
.
Use the eq
matcher only if the order of records matters.
This note describes a Cucumber step definition that lets you say:
Then "Mow lawn" should be an option for "Activity"
But "Reply support mail" should not be an option for "Activity"
Note that this step checks whether an option is available, not that it is selected. There is a separate step to test that an option is selected.
Then /^"([^"]*)" should( not)? be an option for "([^"]*)"(?: within "([^\...
If you run specs or your application and get an error like:
ActionController::MissingFile in 'ProductsController#show, should render PDF'
Cannot read file /some/file.pdf
You may be missing the HTMLDOC binary on your system. Install it like this on Debian/Ubuntu:
sudo apt-get install htmldoc
The idea is this: you take a job that you'd rather not do manually, and describe it to babushka using its DSL. The way it works, babushka not only knows how to accomplish each part of the job, it also knows how to check if each part is already done. You're teaching babushka to achieve an end goal with whatever runtime conditions you throw at it, not just to perform the task that would get you there from the very start.
A check if two date or time ranges A and B overlap needs to cover a lot of cases:
This means you actually have to check that:
A.start > B.end
)B.start > A.end
)Flipping this, A and B overlap iff A.start <= B.end && B.start <= A.end
The code below shows how to implement this in Ruby on Rails. The example is a class `Interv...
Sometimes it is useful to define a named scope by implementing a static method with the scope's name on the scoped class. For instance, when a method should decide which existing scope should be the next link in the scope chain. Take this class for example:
class Meal < ActiveRecord::Base
named_scope :for_date, lambda { |date| :conditions => { :date => date }}
named_scope :with_meat, :conditions => { :meat => true }
named_scope :without_meat, :conditions => { :meat => false }
def self.suitable_for(user)
if user.vegetar...
If you would like to split a Ruby array into pairs of two, you can use the Rails ActiveSupport method in_groups_of:
>> [1, 2, 3, 4].in_groups_of(2)
=> [[1, 2], [3, 4]]
>> [1, 2, 3, 4, 5].in_groups_of(2)
=> [[1, 2], [3, 4], [5, nil]]
>> [1, 2, 3, 4, 5].in_groups_of(2, 'abc')
=> [[1, 2], [3, 4], [5, 'abc']]
>> [1, 2, 3, 4, 5].in_groups_of(2, false)
=> [[1, 2], [3, 4], [5]]
Given group cou...
Then /^I should get a response with status (\d+)$/ do |status|
response.status.should include(status)
end
Then /^I should get a response with status (\d+)$/ do |status|
page.status_code.should include(status.to_i)
end
This card describes a Cucumber step that lets you say:
When I perform basic authentication as "username/password" and I visit the admin area
The path component ("... the admin area") is parsed through your path_to
helper in features/support/paths.rb
.
The step definition is part of Spreewald. The step has been tested with multiple versions of Capybara, Rack::Test and Selenium.
This is a simpler version of the step above:
When /...
When defining a trait using the Modularity gem, you must take extra steps to define constants to avoid caveats (like when defining subclasses through traits).
tl;dr
In traits, always define constants with explicit
self
.
If your trait defines a constant inside the as_trait
block, it will be bound to the trait module, not the class including the trait.
While this may seem unproblematic at first glance, it becomes a problem when including trai...
This is for those who already own an SSL certificate (e.g. using it in the Apache HTTP Server) and need to feed it to a Tomcat application. The main issue is that you need to convert your OpenSSL certificate for Java to use it in its keystore.
This is the place where the application usually gets its keys from. The keytool
is able to read certificate files but does not understand private key files which you need to use y...
Update: This trick probably isn't very useful anymore in Ruby 2.x. The Ruby GC has improved a lot over the years.
Joe Van Dyk discovered that running the Ruby garbage collector only every X seconds can speed up your tests. I found that deferring garbage collection would speed up my RSpec examples by about 15%, but it probably depends on the nature of your tests. I also tried applying it to Cucumber f...
If you’re testing the behavior of deprecated code in your Ruby project, the warning messages littered throughout your spec output is incredibly noisy.
You could silence all warnings with ::ActiveSupport::Deprecation.silenced = true, but you might miss out on an important warning in one of your dependencies. It’s tempting to remove the tests altogether (the code will be burned soon too, right?), but I figured out something a little nicer a little while back in Formtastic’s test suite.
Git allows you to do a binary search across commits to hunt down the commit that introduced a bug.
Given you are currently on your branch's HEAD that is not working as expected, an example workflow could be:
git bisect start # Start bisecting
git bisect bad # Tag the revision you are currently on (HEAD) as bad. You could also pass a commit's SHA1 like below:
git bisect good abcdef12345678 # Give the SHA1 of any commit that was working as it should
# shorthand:
git bisect start <bad ref> <good ref>
Git will fetch a comm...
These steps are now part of Spreewald.
The step definitions below allow you to test the filename suggested by the server:
When I follow "Export as ZIP"
Then I should get a download with the filename "contacts_20110203.zip"
Then /^I should get a download with the filename "([^\"]*)"$/ do |filename|
page.driver.response.headers['Content-Disposition'].should include("filename=\"#{filename}\"")
end
Then /...
The step definitions below allow you to write this in both Webrat and Capybara:
When I follow "Download as PDF"
Then I should get a response with content-type "application/pdf"
Then /^I should get a response with content-type "([^"]*)"$/ do |content_type|
page.response_headers['Content-Type'].should == content_type
end
Then /^I should get a response with content-type "([^"]*)"$/ do |content_type|
response.content_type.should == content_type
end
Unfortunatly this do...
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...
In order to redirect all requests from redirecting-host.com
to desired-host.com
while keeping path and query params unchanged, change your Apache VHost to something like this:
ServerName desired-host.com
ServerAlias redirecting-host.com
RewriteEngine On
RewriteCond %{HTTP_HOST} !^desired-host.com$
RewriteRule ^.*$ http://desired-host.com%{REQUEST_URI} [R=301,L]
Take care to keep all those ^
, $
and !
as seen in the example.
In RSpec 2 shared_examples_for
can have parameters. You can simply hand over arguments from it_should_behave_like
:
shared_examples_for 'string equaling another string' do |expected_string|
it 'should be equal to another string' do
subject.should == expected_string
end
end
describe 'some string' do
subject { 'foo' }
it_should_behave_like 's...
When you need to see the content of a page (i.e. not all the HTML but the relevant text body)
pp (html_content)
body
or response.body
page.driver.html.content
page.body
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...
You can usually just use the eq
matched to compare two numbers:
expect(deal.total).to eq(120)
If the actual value is a BigDecimal
, you might have issues when you match it against a Float
:
expect(deal.total_price).to eq(1200.99)
In these cases, try matching it against another BigDecimal
:
expect(deal.total_price).to eq BigDecimal(1200.99)
If you don't like the syntax, our rspec_candy gem has a matcher that will compare Fixnums
(integers), Floats
and `BigDecima...
You can use these step definitions:
Then /^I should not see an error$/ do
(200 .. 399).should include(page.status_code)
end
Then /^I should see an error$/ do
(400 .. 599).should include(page.status_code)
end
Note that you need to tag the scenario with @allow-rescue
to test that an error is shown like this
@allow-rescue
Scenario: Accessing the admin area requires a login
When I go to the admin area
Then I should see an error
These step definitions will not work for @javascript
scena...
When you eagerly load an association list using the .include
option, and at the same time have a .where
on an included table, two things happen:
where
condition, even though you only wanted to use the where
condition to filter the containing model.The second case's behavior is mostly unexpected, because pre-loaded associations usually don't care about the circumstances under whi...