Stub methods on any instance of a class in Rspec 1 and Rspec 2
RSpec 1 (Rails 2)
With the most recent spec_candy.rb
helpers you can say:
User.stub_any_instance(:foo => :bar)
user = User.new
user.foo
# => :bar
RSpec 2 (Rails 3)
RSpec 2 comes with this feature built in:
User.any_instance.stub(:foo => :bar)
user = User.new
user.foo
# => :bar
RSpec 3
-------...
Show the character set and the collation of your MySQL tables
To show the collation of your tables you have to login to the MySQL console and execute SHOW TABLE STATUS FROM database;
mysql> SHOW TABLE STATUS FROM test;
+-------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_leng...
Show and change MySQL default character set
To show the MySQL default character set you have to login to the MySQL console and execute SHOW VARIABLES LIKE 'char%';
mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| chara...
Creating a patch in git and how to apply patches
You can convert git commits into patch files. Those can be used to apply to a different repository [1] or by someone else (e.g. sent when sent to them via e-mail).
Creating a patch in git
- Make your changes and commit them.
- Run
git format-patch COMMIT_REFERENCE
to convert all commits since the referenced commit (not including it) into patch files.
For example, let's say you prepared 2 commits. Run:
git format-patch HEAD~~
This will create 2 files, one for each commit since HEAD~~
, like these:
00...
Using :dependent => :destroy – Issues with 'code arrangement' or 'cached objects'
First keep in mind that :dependent => :destroy
hooks into before_destroy
.
So when you use other before_destroy
callbacks the sequential arrangement of your code may be important.
For example:
class Container < ActiveRecord::Base
before_destroy :a_callback
has_many :items, :dependent => :destroy
end
results in
container.destroy
# => a_callback
# => container.items.destroy_all
but
class Container < ActiveRecord::Base
has_many :items, :dependent => :destroy
before_...
Fix multiple CKEditor instances using jQuery adapter - fixed since 4.2
Using the jQuery adapter breaks the built-in save function of CKEditor.
Phenomenon: The page is submitted correctly, but the original values of the form fields were posted instead of what was typed in the editors.
Work around: Basicly instead of initiating the editor using the above example I ended up using the following:
$( 'textarea.editor').each( function() {
CKEDITOR.replace( $(this).attr('id') );
});
Note: This assumes that each field using the editor has its own unique ID.
Rails logs are not flushed automatically (in Rake tasks)
The Rails logger will store its content in a buffer and write it into the file system every 1000 lines. This will come back to bite you when using Rails.logger.info
to write log output during Rake tasks or on a production console.
You often won't notice this because for the development
and test
environments auto_flushing
is set to write after each line. On production environments the Rails logger writes only every 1000 lines -- and not upon shell or script ter...
Why your Cucumber feature loses cookies when run under Selenium
When your Cucumber feature seems to forget cookies / sessions when you run it with Selenium check if the test travels in time like here:
Given the date is 2017-10-20
When I sign in
Then I should see "Welcome!"
What happens here is that the Rails application serving pages runs in 2017, but the process running your browser still lives today. This huge gap in time will expire most cookies immediately.
If all you need is to freeze the time to a date, a workaround is to travel to the future instead.
You can use any RSpec matcher to match arguments of method calls
RSpec lets you define the arguments with which you expect a method to be invoked:
subject.should_receive(:say).with('hello')
Sometimes you don't care about the exact arguments. For such cases RSpec comes with argument constraints like anything
or hash_including
:
subject.should_receive(:update_attributes).with(hash_including(:message => 'hi world'))
You can go even further and use any R...
Don't call gsub on safe strings
Calling #gsub
on a string that was previously marked as #html_safe
will lead to unexpected behavior. E. g. backreferences to captured groups ($1
, $2
) will be nil
even if the group was matched.
There is no universal workaround available since you can't expect #html_safe
strings to still be safe after using gsub
on them.
You can, however, fix the $1
gsub
behavior on html_safe strings.
Capybara can match elements outside of <body>
Capybara will match elements outside of a page's <body>
tag.
For example, the step definitions below match <link>
nodes in a page's <head>
:
Then /^my browser should auto-discover the "([^"]*)" feed$/ do |slug|
page.should have_css(
'head link' +
'[rel="alternate"]' +
"[href='http://www.example.com/#{slug}/feed.rss']" +
'[title="RSS feed (all cards)"]' +
'[type="application/rss+xml"]',
visible: false
)
end
Then /^my browser should not auto-discover any RSS fe...
Mailcatcher: An alternative to inaction_mailer
Looks simpler than inaction_mailer:
gem install mailcatcher
mailcatcher
Setup Rails to send mails to 127.0.0.1:1025. Usually you want the following config in config/environments/development.rb
and maybe in test.rb
or cucumber.rb
.
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => 'localhost',
:port => 1025
}
Now you can see sent mails in your browser when opening http://127.0.0.1:1080
Note: In order to s...
How to change the order of nested forms being rendered (especially blank forms)
Generally for nested forms, a blank form is placed below all other existing object forms. If you would like to change the position of the blank form(s) you can reorder the object's one-to-many association. For example you can put the blank form on top with the following snippet:
actors = movie.actors
actors.build
actors.unshift(actors.pop(1)) # won't work with Rails 4+
Because build_for_form
creates new objects and ap...
Git: Change author of a commit
Using git rebase
can be painful but luckily you can resort to cheating with git reset
and committing anew.
Now what if you wanted to rebase commits of other people and still wish them to be the authors of their code? Easy: make them the author of a commit you made.
When you have freshly staged changes that are ready to be committed, just use the --author
switch:
git commit -m "Hello Universe" --author="Philip J Fry <someone@example.com>"
If...
Removing ANSI color codes from Rails logs
The colors in Rails log files are helpful when watching them but, since they are ANSI color codes like ^[[4;36;1m
, can be annoying when you are reading the logs with a tool that does just prints those control characters (like less
or vim
).
Remove them with sed
:
cat staging.log | sed -r "s/\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g"
This will print the log without colors to your terminal. You can pipe the result into less
for example.
To have a file you can vim
around with, just write that output into a new file:
ca...
Usage of RSpec's raise_error
Never use raise_error
without specifying the Error you expect.
expect { do_a_lot_of_complicated_stuff }.to raise_error
will be green if you make any error in programming. E.g. a simple typo would make the test above green. The block will catch the Spec::
exception and the test will be happy.
Be sure to always have custom errors in your models and raise them in a manner that lets you know what went wrong.
expect { execute_payment! }.to raise_error(PayPal...
Test that a form field has an error with Cucumber and Capybara
You can use the step definition below to say this:
Then the "Last name" field should have an error
Capybara
Then /^the "([^\"]*)" field should( not)? have an error$/ do |field, negate|
expectation = negate ? :should_not : :should
page.send(expectation, have_css('.field_with_errors', :text => field))
end
MySQL: For each group, retrieve a comma-separated list of values in a given column
The technique described in this card has an important caveat: The result of GROUP_CONCAT
is truncated to the maximum length that is given by the group_concat_max_len
system variable, which has a default value of 1024. This will cause horrible, data-destroying bugs in production. For this reason you should probably not use GROUP_CONCAT
ever. At least you must set the value of group_concat_max_len
to an insanely high value on every database server your application runs on.
Lik...
Using heredoc for prettier Ruby code
You can use heredoc to avoid endlessly long lines of code that nobody can read. Heredoc strings preserve linebreaks and can be used like this:
def long_message
puts(<<-EOT)
Here goes a very long message...
Sincerely,
foobear
EOT
end
<<-EOT
will be somewhat of a placeholder: anything you write in the line after you used it will be its value until you write EOT
in a single line.
You can use any string to flag your heredocs. To be more verbose you...
Change / Update SSL certificate for Amazon Elastic Load Balancer
There is a new card about how to do this with the new AWS Command Line Interface
At first you need the IAM Cli Tools.
-------------------------------------------------------------------------------------------------------------...
Disable output when using cURL
cURL makes a web request and shows you the response body.
You can redirect the response body to /dev/null
just like for many other programs. But if you do that, cURL will display some short information about the request you are making:
$ curl http://www.example.com/ > /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 30865 100 30865 0 0 4793 0 0:00:06 0:00:06 --:--:-- 10199
If you wan...
Make an HTTP request to a machine but fake the hostname
Consider you have a website vhost listening to www.example.com
, redirecting all incoming requests that do not talk about the configured hostname (this is often used to redirect users to http://www.example.com
when entering only http://example.com/
).
If you want to make a request to that site's web server without actually talking to www.example.com
(e.g. because this is a load balancer's address but you want to access one specific machine), you cannot just request machine1.example.com
or localhost
as the above vhost will redirect...
"Address already in use" with autossh
If you get an error "Adress already in use" with autossh check with lsof
or netstat
if something already listen on the Ports you want to use.
There are three Ports you have to look at. If your Command look like this:
/usr/local/bin/autossh -f -M 5100 -g -N -C -L 8080:127.0.0.1:80 example.com -i ~/.ssh/id_rsa -l user
The following three ports need to be available:
- 8080: The Port you want the tunnel to listen
- 5100: The Autossh Monitoring Port
- 5101: Autossh also uses the Monitoring Port +1
How to install a frozen version of Firefox for your Selenium tests
Whenever Firefox updates, all your Cucumber features that use Selenium break. This is annoying.
In order to remedy this, version 0.5.0 of our geordi gem comes with a script that helps you create an unchanging version of Firefox for your Selenium tests. In particular, this new copy of Firefox will have the following properties:
- It won't update itself with a newer version
- It can co-exist with your regular Firefox installation (which you can update at will)
- It will use a profile separate from the one...