Posted by
Barry – July 9, 2010
I'm using Mongoid and MongoDB on a new project, so my models are not derived from ActiveModel. On previous projects I just used the validates_url_format_of plugin, but for this project I put the code from the module into an initializer (config/initializers/validation.rb) and used extend.
module ValidatesUrlFormatOf
IPv4_PART = /\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]/ # 0-255
REGEXP = %r{
\A
https?:// # http:// or https://
([^\s:@]+:[^\s:@]*@)? # optional username:pw@
( (([^\W_]+\.)*xn--)?[^\W_]+([-.][^\W_]+)*\.[a-z]{2,6}\.? | # domain (including Punycode/IDN)...
#{IPv4_PART}(\.#{IPv4_PART}){3} ) # or IPv4
(:\d{1,5})? # optional port
([/?]\S*)? # optional /whatever or ?whatever
\Z
}iux
DEFAULT_MESSAGE = 'does not appear to be a valid URL'
DEFAULT_MESSAGE_URL = 'does not appear to be valid'
def validates_url_format_of(*attr_names)
options = { :allow_nil => false,
:allow_blank => false,
:with => REGEXP }
options = options.merge(attr_names.pop) if attr_names.last.is_a?(Hash)
attr_names.each do |attr_name|
message = attr_name.to_s.match(/(_|\b)URL(_|\b)/i) ? DEFAULT_MESSAGE_URL : DEFAULT_MESSAGE
validates_format_of(attr_name, { :message => message }.merge(options))
end
end
end
Then my model extends that module:
class Location
include Mongoid::Document
include Mongoid::Timestamps
extend ValidatesUrlFormatOf
validates_url_format_of :url, :allow_blank => true
...
Posted by
Barry – July 6, 2010
Here's how I test my admin controllers that use HTTP basic authentication using RSpec 2:
before(:each) do
user = 'test'
pw = 'test_pw'
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
end
Actually, that's how I did it when I first tested things, but I've since put it in its own module under spec/support/auth_helper:
module AuthHelper
# do admin login
def admin_login
user = 'test'
pw = 'test_pw'
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
end
end
and now my controller spec looks like this:
describe Admin::LocationsController do
include AuthHelper
before(:each) do
admin_login
end
describe "GET index" do
it "assigns all locations as @locations" do
loc = Factory.create(:location)
get :index
assigns(:locations).should eq([loc])
end
end
describe "GET show" do
it "assigns the requested location as @location" do
loc = Factory.create(:location)
get :show, :id => loc.id
assigns(:location).should === loc
end
end
end
That "Factory" line comes from my use of factory_girl rather than fixtures.
Posted by
Barry – July 5, 2010
After wrestling with various combinations of cleaning out my database between tests, this is what I'm using on a new Rails 3 application that uses Mongoid, RSpec 2, and Database Cleaner. I have one table (neighborhoods) which is populated using rake db:seed, so I'm excluding that from the cleanup.
Put this into your spec/spec_helper.rb:
require 'database_cleaner'
RSpec.configure do |config|
config.mock_with :rspec
config.before(:each) do
DatabaseCleaner.orm = "mongoid"
DatabaseCleaner.strategy = :truncation, {:except => %w[ neighborhoods ]}
DatabaseCleaner.clean
end
end
UPDATE: This isn't working for me now. Apparently the config.before(:each) part isn't being called in the versions of rspec (2.0.0.beta.21), cucumber (0.8.5), and cucumber-rails (0.3.2) that I'm using now. I'm now using the approach by Kevin Faustino here.