RSpec – Running One Single Test at a Time
In the old days I would pass a regular expression to run a particular unit test or group of similarly named unit tests by name.
Here’s the easy way to run one test in RSpec… by line number!
Look at the line-number of any RSpec block (it, describe, etc), and simply run the rspec command, passing in the [filename]:[line number]:
$ rspec models/user_spec.rb:27
Happy testing!
Rails Rotating Log Files with logrotate
I know there’s a way to specify Rails log rotation parameters directly in the app. This works for some people:
# Can place this in environment.rb
# 2nd argument - number of log files to keep
# 3rd argument - size (bytes) that log files are allowed to reach before rotation
config.logger = Logger.new(config.log_path, 8, 1024)
However…. I like the customizability of using logrotate better!
Here’s my logrotate config file that handles weekly log rotation, delayed compression and uses the copy-truncate method:
I place this config in the /etc/logrotate.d folder (ubuntu)
(ie. /etc/logrotate.d/<rails_app_name>)
/var/www/rails//shared/log/production.log {
weekly
missingok
rotate 8
compress
delaycompress
notifempty
copytruncate
}
This config will rotate my production.log file weekly, keeping at most 8 log files. It delays compression until next rotation (extra precaution, simply to make sure the log file is not in use), and uses the ‘copytruncate’ method which basically copies the current log file, and then truncates this log file, so the Rails app maintains file pointer for continued writing.
RSpec Request Spec to Test Rails / Grape API Functionality
I finally got around to trying Grape – a “RESTful API microframework built to easily and quickly produce APIs for Ruby-based web applications”. This is a project still in baby stages, but has a lot of potential and worth exploring for anyone creating a Rack-based API in Ruby, not necessarily Rails!
Now, after creating a pretty basic API that used HTTP Basic Authentication, I was inclined to write some RSpec tests to make sure my API was working the way I thought it was (.. or because I am obsessed with well-tested, beautiful code..).
After some thought, I decided that the best way to test my API was with RSpec “request” specs. Now, if you are at all relatively new to RSpec (I was a Test::Unit kinda guy before), it might not be completely obvious that “request specs” are basically what I have come to know as “integration tests”, testing high-level functionality that spans multiple controllers and multiple requests – (think: a user’s interaction with the app).
My reasoning for choosing request specs is because I want to test specific API URL endpoints routed the way I expected. (Routing is handled magically by Grape with a simple mount in the config/routes.rb file). API testing just kinda makes sense to handle in request specs.
Anyways, I ran into a couple issues because in REQUEST specs, you do not have access to the @request object (haha?), as you do in controller specs. Now, in order to mock HTTP Basic Authentication, you need to mock the request object to send headers along with the GET request.
Well, solution: It turns out you can pass headers into your get() method! I only wish I had discovered that an hour ago!
Here’s a simple excerpt from my API request specs that shows how to mock the HTTP basic authentication and test your API functionality:
With NO basic auth, it’s just a simple GET request
it 'should return a 401 with no basic auth to /api/v1/rewards' do
get '/api/v1/rewards'
response.code.should == '401'
response.body.should == "Unauthorized - Please check your username and password"
end
To mock the basic auth, simply pass header hash as argument to the GET request! No need to access the request object here.
it 'should return a 200 with valid basic auth to /api/v1/rewards' do
# Uses basic_auth helper method
credentials = basic_auth('testuser','test')
get '/api/v1/rewards', nil, {'HTTP_AUTHORIZATION' => credentials }
response.code.should == '200'
response.body.should == "..."
end
# You can define this at the bottom of your spec file, or in spec_helper for convenience
def basic_auth(user, password)
ActionController::HttpAuthentication::Basic.encode_credentials user, password
end
Hope this helps someone else. Now go write some request specs!
Create a link in Javascript with the .link method
Now I don’t claim to be a Javascript expert, but I thought I knew the basics pretty well! Here’s a little-known method built into Strings that creates a link tag:
html = 'click me'.link('http://example.com')
which results in:
html = '<a href="http://example.com">click me</a>'
Wordpress Plugin – track referrers based on url GET parameters using regular expressions
First of all, all the credit and thanks to Marios Alexandrou for his wordpress plugin Social Media Alerts for Wordpress, which allows you to set up email notifications when certain query-strings are received to your wordpress site!
For example, if you wish to see when visitors come to your site from Twitter, you can specify a query string of “source=twitter”. When visitors come to your page with this parameter on the URL (ie. http://yoursite.com/?source=twitter) then this will be tracked, and you can be notified by email.
I installed this plugin but besides specifying the literal query-string, I wanted to be able to handle dynamic query-strings based on regular expressions that I could define. For example, I wanted to track all query-strings that matched “http://mysite.com?ref=..”.
This would track visits to anything where the query string matched “ref=…”. For example, “http://mysite.com?ref=twitter”, “http://mysite.com?ref=facebook”, “http://mysite.com?ref=digg”, etc.
Here’s my little bit of code to the plugin to support regular expressions :
# File: social-media-email-alerts.php
# Line: 142
# Replace the existing "get_query" function definition with this:
function get_query($qs){
global $wra_sites;
if ($qs) {
$query = explode("&",$qs);
foreach($query as $query_string){
if(is_array($wra_sites[$query_string])){
return $query_string;
}
}
# Added for regexp matching on query string
foreach($query as $query_string){
foreach($wra_sites as $key => $val){
if (preg_match($key, $query_string) > 0) {
return $key;
}
}
}
}
return false;
}
As you can see, it’s just a single foreach block that will match a query-string by regex, and return if found. Now it’s possible to add a rule for /^ref=.+/ that will alert me upon any match to this regular expression.
