Since for the last couple of months I’m all about test-driven development I wanted to test a couple of ActiveRecord callbacks that relied on Date.today method.
Here’s a quick hack for your test_helper.rb file that allows you to specify the date returned by Date.today.
class Date
class << self
@@mocked_today = nil
alias :unmocked_today :today
def today
@@mocked_today || unmocked_today
end
def with_mocked_today(mocked_today)
if block_given?
@@mocked_today = mocked_today
begin
yield
ensure
@@mocked_today = nil
end
end
end
end
end
And a quick example how to use it:
Date.with_mocked_today Date.parse("2008-01-01") do
// your code here...
end
Webrat (acceptance framework for Ruby) has a nasty habit of sending text/plain Content-Type when testing file uploads. This causes validates_attachment_content_type Paperclip validation to fail.
Example test (using Shoulda):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # test
require File.dirname(__FILE__) + "/../test_helper"
class PhotoTest < ActionController::IntegrationTest
context "any user" do
should "be able to upload a photo" do
visit new_photo_path()
attach_file "photo_photo", File.dirname(__FILE__) + "/../uploads/photo.jpg"
click_button "Add photo"
assert_contain "Uploaded!"
end
end
end
# model
class Photo < ActiveRecord::Base
has_attached_file :photo, :styles => { :main => "640x480#" },
:path => ":rails_root/public/images/photo/:id/:style.:extension",
:url => "/images/photo/:id/:style.:extension"
validates_attachment_presence :photo
validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg']
end |
This will always fail (due to text/plain Content-Type).
Kinda nasty hack in my test solved the problem (line 3-7):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class PhotoTest < ActionController::IntegrationTest
context "any user" do
setup do
Photo.class_eval do
validates_attachment_content_type :photo, :content_type => ["text/plain"]
end
end
should "be able to upload a photo" do
visit new_photo_path()
attach_file "photo_photo", File.dirname(__FILE__) + "/../uploads/photo.jpg"
click_button "Add photo"
assert_contain "Uploaded!"
end
end
end |
Any better ideas? Hacking Webrat’s mime.rb was also an option, but I didn’t like it.
Recently I’ve been creating new Ruby on Rails applications like a mad-man. I like to keep my stuff in a repository from the very beginning and this ment setting up Git / Subversion for each application.
So came up with a simple script which runs like this:
./rails-git my_application
This sets up a Rails application, Git repository and freezes Rails gems. Enjoy!
#!/bin/bash
if [ "$1" = "" ]
then
echo "usage: ./rails-git project_name"
exit
fi
echo "Creating Rails app..."
rails $1 > /dev/null
echo "Initializing git repository..."
cd $1
git init > /dev/null
cat >> .gitignore << EOF
log/*.log
tmp/**/*
config/database.yml
EOF
touch log/.gitignore
touch tmp/.gitignore
mv config/database.yml config/database_example.yml
echo "Initial import..."
git add . > /dev/null
git commit -m "$1 initial import" . > /dev/null
echo "Freezing Rails gems..."
rake rails:freeze:gems > /dev/null 2>&1
git add vendor/rails > /dev/null
git commit -m "freezing rails gems" > /dev/null
echo "Done!"
Should you require to use GNU sed instead of the default OS X BSD sed and you have MacPorts installed just go to your Terminal.app and type:
Now you have GNU sed installed – though if you don’t want to type gsed instead of sed then create a symbolic link:
sudo ln -s /opt/local/bin/gsed /opt/local/bin/sed
No MacPorts? You can compile sed from scratch check Mark Chen’s post.
Tired of typing ./script/server? Yeah, me too. Especially with Lighttpd / FastCGI configured for PHP at hand on my development machine – pure envy. So I gave a try with my Ruby on Rails applications.
Easy as pie – first add a custom domain to your /etc/hosts:
Then – add FastCGI handler to your lighttpd.conf
$HTTP["host"] =~ "myapp.local" {
server.indexfiles = ( "dispatch.fcgi" )
server.document-root = "/path/to/myapp/public/"
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = (
".fcgi" =>
( "localhost" =>
(
"socket" => "/tmp/myapp.socket",
"bin-path" => "/path/to/myapp/public/dispatch.fcgi",
"bin-environment" => ( "RAILS_ENV" => "development" )
)
)
)
}
Restart your Lighttpd and your done. Unless…
Unless you require some custom libs in your Ruby on Rails application. Then you should modify your code (I keep all my require statements in myapp/config/initializers/requires.rb) from:
to:
require Rails.path.join("mylib.rb")
No more those nasty 500’s! This setup will also work for subdomains, ie. thisis.myapp.local (as long you as handle them /etc/hosts or anywhere else).
Some of my current JavaScript development is done with Prototype. Launching default JavaScript events with Prototype seems to be kind of awkward – Element.fire method simply won’t work.
I came up with quite a nasty workaround:
Event.observe( window, 'load', function() {
$$( '.my_element' ).each( function(element) {
Event.observe(element, 'onchange:fake', myMethod);
element.fire( 'onchange:fake' );
} );
} );
I wish this could be done in a more elegant way. Anybody?
I’ve been on-and-off developing a couple of Ruby On Rails applications and since most of them are in the “just for fun” stage I was using my Google Apps account for e-mail delivery. However, I kept on getting argument count error in smtp_tls.rb (a library required for proper e-mail delivery via smtp.gmail.com server) – both on my development and staging machine. I know, I know, I should get a dedicated box and become a real man, but for now my Dreamhost account should be enough (hey, it’s for blogging and fun, not production!).
But back to the problem – I kept on fixing smtp_tls.rb until this morning a lightbulb popped over my head. Yes, check_auth_args in Net::SMTP takes different arguments in Ruby 1.8.7 (which I’m using for development) and in Ruby 1.8.6 (staging).
In order to make things right just do some Ruby version checking (see lines 9 – 13):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| require "openssl"
require "net/smtp"
Net::SMTP.class_eval do
private
def do_start(helodomain, user, secret, authtype)
raise IOError, 'SMTP session already started' if @started
if RUBY_VERSION == "1.8.7"
check_auth_args user, secret
else
check_auth_args user, secret, authtype if user or secret
end
sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
@socket = Net::InternetMessageIO.new(sock)
@socket.read_timeout = 60 #@read_timeout
check_response(critical { recv_response() })
do_helo(helodomain)
if starttls
raise 'openssl library not installed' unless defined?(OpenSSL)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
ssl.connect
@socket = Net::InternetMessageIO.new(ssl)
@socket.read_timeout = 60 #@read_timeout
do_helo(helodomain)
end
authenticate user, secret, authtype if user
@started = true
ensure
unless @started
# authentication failed, cancel connection.
@socket.close if not @started and @socket and not @socket.closed?
@socket = nil
end
end
def do_helo(helodomain)
begin
if @esmtp
ehlo helodomain
else
helo helodomain
end
rescue Net::ProtocolError
if @esmtp
@esmtp = false
@error_occured = false
retry
end
raise
end
end
def starttls
getok('STARTTLS') rescue return false
return true
end
def quit
begin
getok('QUIT')
rescue EOFError
end
end
end |
In his post Matthias Georgi showed how to view RI in a web browser. He’s using Apache, so I rolled out a couple of snippets for lighttpd users.
First I added a host to my /etc/hosts:
And created a virtual host in my lighttpd.conf
$HTTP["host"] =~ "ri" {
server.document-root = "/my/projects/path/ri/"
cgi.assign = ( ".rb" => "/usr/bin/ruby" )
url.rewrite-once = (
"^(.*)$" => "ri.rb?$0"
)
}
Since lighttpd has a diffrent way of handling mod_cgi request parameters Matthias’es script needed a little adjusting:
#!/usr/bin/env ruby
require 'rdoc/ri/ri_driver'
require 'rubygems'
print "Content-type: text/html\r\n\r\n"
ARGV << ENV["QUERY_STRING"].sub("/", "") << '-f' << 'html' <<
ri = RiDriver.new
print '<html><body style="width:600px; margin:auto; padding:20px"><pre>'
ri.process_args
print '</body></html>'
Restart your lighttpd, browse to http://ri/String.capitalize. That’s it!
Some API changes in Ruby On Rails broke thorny-sun’s prawnto (Prawn based PDF templating plugin). I’ve just pushed a quick fix for it to github – you can pull it from http://github.com/filiptepper/prawnto/tree/master. Enjoy!
For my current project instead of rolling out my own form builder I went for the github’s air_budd_form_builder. It generates nice, semantic HTML code. This project also required localized_country_select, so in order to make these plugins compatible I had to prepare this little snippet:
module AirBlade
module AirBudd
class FormBuilder
def input_type_for(field_helper)
case field_helper
when 'text_field'; 'text'
when 'text_area'; 'text'
when 'password_field'; 'password'
when 'file_field'; 'file'
when 'hidden_field'; 'hidden'
when 'check_box'; 'checkbox'
when 'radio_button'; 'radio'
when 'select'; 'select'
when 'date_select'; 'select'
when 'time_select'; 'select'
when 'country_select'; 'select'
when 'localized_country_select'; 'select'
else ''
end
end
end
end
end
module AirBlade
module AirBudd
class FormBuilder
%w( localized_country_select ).each do |name|
create_collection_field_helper name
end
end
end
end
Put it in your application’s lib directory and enjoy!