Sleight of Hand for the Ruby Man
June 12th, 2008
Chad Humphries pointed me to this tasty bit of code. Since Ruby so graciously lets you open up classes anywhere, it’s nice to know where the right place to debug is. Simply put the following code into a globally accessible place (I just used .irbrc) and you will have the method available.
module Kernel
# which { some_object.some_method() } => ::
def where_is_this_defined(settings={}, &block)
settings[:debug] ||= false
settings[:educated_guess] ||= false
events = []
set_trace_func lambda { |event, file, line, id, binding, classname|
events << { :event => event, :file => file, :line => line, :id => id, :binding => binding, :classname => classname }
if settings[:debug]
puts "event => #{event}"
puts "file => #{file}"
puts "line => #{line}"
puts "id => #{id}"
puts "binding => #{binding}"
puts "classname => #{classname}"
puts ''
end
}
yield
set_trace_func(nil)
events.each do |event|
next unless event[:event] == 'call' or (event[:event] == 'return' and event[:classname].included_modules.include?(ActiveRecord::Associations))
return "#{event[:classname]} received message '#{event[:id]}', Line \##{event[:line]} of #{event[:file]}"
end
# def self.crazy_custom_finder
# return find(:all......)
# end
# return unless event == 'call' or (event == 'return' and classname.included_modules.include?(ActiveRecord::Associations))
# which_file = "Line \##{line} of #{file}"
if settings[:educated_guess] and events.size > 3
event = events[-3]
return "#{event[:classname]} received message '#{event[:id]}', Line \##{event[:line]} of #{event[:file]}"
end
return 'Unable to determine where method was defined.'
end
end
Once you have that you can simply open up script/console or irb and give it a whirl
>> where_is_this_defined {Streamlined.ui_for(:foo)}
=> "Streamlined received message 'ui_for', Line #6 of /Users/abedra/src/someapp/trunk/lib/extensions/streamlined/streamlined.rb"
This tells us that the ui_for method of streamlined is actually being called from an extension that the project made rather than the streamlined plugin itself. This would save you lots of time trying to debug the wrong method! Give it a try.
Rails on OpenBSD 4.3
June 7th, 2008
OpenBSD released version 4.3 of their OS on May first. This version is especially exciting because there has been considerable effort made by the ports contributors to get the Rails stack up to date. This makes setting up a server with OpenBSD considerably easier than my last set of posts regading deploying with OpenBSD. A few things have changed, but the idea is the same, so I will run through a full stack setup from a scratch install. If you need information on installing OpenBSD there is a great tutorial that will get you started.
Post Install
You will be greeted with a vanilla install and not a whole lot to work with. Let’s get some basic sytem tools installed. We will use OpenBSD’s pkg_add tool to get us up and running quickly. The stack we will setup will include:
- Helpful system tools
- Ruby / Rails
- Thin
- MySQL
- nginx
Helpful System Tools
# build the locate database
% /usr/libexec/locate.updatedb
# setup pkg_add path for easy installs
% export PKG_PATH=ftp://ftp.openbsd.org/pub/OpenBSD/4.3/packages/i386/
# install bash (optional)
% pkg_add -i bash
% chsh -s bash
# install other needed system tools. we use pkg_add with the -i
# flag for interactive mode. this way it will ask you what version
# of a specific software you want if there is more than one available.
% pkg_add -i curl nano subversion git
Ruby / Rails / Thin
% pkg_add -i ruby ruby-iconv ruby-gems
% gem update --system
% gem install rails thin
# if you want to use thin with sockets you will need to install
# eventmachine from source to get version 0.11
% gem install eventmachine --source http://code.macournoyer.com
MySQL
% pkg_add -i mysql-server
% mysql_install_db
# start mysql
% mysqld_safe &
Create the file /etc/rc.conf.local and place the following into it.
mysql="YES"
Now open up /etc/rc.local and add the following script just before the ending echo ”.”.
if [ X"${mysql}" == X"YES" -a -x /usr/local/bin/mysqld_safe ]; then
echo -n " mysqld"; /usr/local/bin/mysqld_safe --user=_mysql --log --open-files-limit=256 &
for i in 1 2 3 4 5 6; do
if [ -S /var/run/mysql/mysql.sock ]; then
break
else
sleep 1
echo -n "."
fi
done
fi
This will setup mysql to start when the system boots.
nginx
% pkg_add -i nginx
Then open up /etc/rc.local and add the following after your mysql entry.
if [ -x /usr/local/sbin/nginx ]; then
echo -n ' nginx'; /usr/local/sbin/nginx
fi
This will setup nginx to start when the system boots. I like to modify my nginx configs a little bit taking a little away from the debian linux apache2 and nginx configs.
% cd /etc/nginx
% mv nginx.conf nginx.conf.orig
% mkdir sites-available
% mkdir sites-enabled
% curl -O http://aaronbedra.com/nginx.conf
% cd sites-available
% curl -O http://aaronbedra.com/vhost
This will enable nginx to automagically load any vhost file that is in sites-enabled. We use the sites-available and sites-enabled directories and symlink from one to another. I prefer this, you don’t have to do this if you already have an nginx setup you like to use. Assuming you followed the above steps the only thing you have left to do is edit the vhost file and add your sites information. I would suggest renaming the vhost file to something a little more descriptive as well. Don’t forget to create the directory in /var/log/nginx/yoursite or nginx will fail to start. Once you have completed that you just need to symlink your new config into sites-enabled and restart nginx.
% ln -s /etc/nginx/sites-available/vhost /etc/nginx/sites-enabled/vhost
# start nginx
% nginx
# restart nginx
% kill -HUP `cat /var/run/nginx.pid`
Post Setup Notes
There is one small problem with eventmachine on OpenBSD. When thin intializes eventmachine at application boot time, it tries to use the wrong eventmachine library. You need to use the pure ruby version. An easy way to fix this is to add the following to your .profile
export EVENTMACHINE_LIBRARY="pure_ruby"
This will make eventmachine happy and thin able to run. The reason for choosing thin and nginx over the other implementations is because thin can connect to to nginx via sockets, and nginx is just plain easier to configure, not to mention faster. Obviously you can season this setup to taste if you prefer other stack implementations.
Surviving the Reboot
It’s good practice to have a thin config file that can start your application. Let’s take a look at how to configure thin for your app.
% mkdir /etc/thin
% thin config -C /etc/thin/your_config.yml -s2 -S /tmp/thin.sock
This will create a thin config file that will spawn to instances of thin (s2) and use sockets instead of ports. You can change the number of instances it spawns or where you want to put your sockets if you so desire. Now that you have a running system, you just need to add one more thing to make sure that your app starts if your server reboots. To make this work you need to do two things.
% ln -s /usr/local/bin/thin /usr/bin/thin
This will make sure thin is available at boot time. Next you need to add a line in etc/rc.local to start your app. Add this after the other startup scripts you added previously.
echo -n " thin"; thin start -C /etc/thin/your_config.yml
Happy OpenBSD-ing!
Railsconf Talk
June 1st, 2008
Here are the slides from my railsconf talk. Thanks for all of you that showed up and gave support!
Shame on you O'Reilly!
May 30th, 2008
I have a bone to pick with the mensa that decided that it was important to give each Railsconf attendee a badge that had all of their personal information encoded on a barcode on the back side.
From the back of the badge:
“Your name, email address, job title, organization, address and phone number are encoded on this card. Please recycle this card at the end of the conference”
What? Is there a magical card swiper that gives you money and ever lasting happiness? Exactly why do I need to carry around a badge with all that information? Do they really expect me to give it back to someone else for “recycling” at the end of the conference? This is one badge that is going in the shredder!
Refactotum Time!
May 29th, 2008
The crew is doing a tutorial today at Railsconf 2008 in Portland. We will be presenting on contributing to open source projects. There will be a short demo of some of the tips and tricks we use when we are contributing, followed by a couple hours of open time to contribute to your favorite open source projects. Bring your laptop and join the fun! We are going to be focusing on projects hosted with git, so if you haven’t already installed it, now is the time.
Rails Security Audit Peepcode is now Available!
May 28th, 2008
I just finished writing a pdf book for Peepcode Screencasts about security auditing Rails applications. The book covers all the high level concepts needed to properly determine and fix security related problems in your code and on your servers. The contents include:
- Cross Site Scripting
- Model Security and SQL Injection
- Fuzzing Testing / Spidering
- Server Security
- Risk Ananlysis
This book is a must have for any serious Rails developer exposing their applications to the web. The best part is you can get your very own copy right now for only $9! Peepcode has also recently released a few more great books, so it might be a good time to pony up for a 5 or even 10 pack and sharpen your development skills.
MBTI Meme
April 25th, 2008
meaning I am Extroverted, favor intuition, thinking, and perception. The test I took is free and can be found here. What type are you?
Tagging: Rob, Muness, Jason, Joe, and Evan
Announcing Fixture Busters... {dot}com
April 18th, 2008
You can find the site at http://fixturebusters.com. It will have some super duper styling love and the first screencast up sometime in the next week so stop on over and check it out!
MPI Ruby - Officially Released
April 17th, 2008
git://github.com/abedra/mpi-ruby.git
If you are running leopard and have XCode Tools installed, all you have to do is:
$ ./configure
$ make
$ sudo make install
and you should be in happy parallel land. If you don't have the new Apple hotness, you need to install OpenMPI.
Happy high performance parallel computing!
MPI Ruby lesson - Basic Communication
April 17th, 2008
1 2 3 4 5 6 7 8 9 10 11 12 13 |
myrank = MPI::Comm::WORLD.rank() csize = MPI::Comm::WORLD.size() if myrank % 2 == 0 then if myrank + 1 != csize then hello = "Hello, I'm #{myrank}, you must be #{myrank+1}" MPI::Comm::WORLD.send(hello, myrank + 1, 0) end else msg, status = MPI::Comm::WORLD.recv(myrank - 1, 0) puts "I'm #{myrank} and this message came from #{status.source} with tag #{status.tag}: '#{msg}'" end |
$ mpirun -np 16 mpi_ruby basic.rb
We get an output similar to this:
I'm 13 and this message came from 12 with tag 0: 'Hello, I'm 12, you must be 13'
I'm 1 and this message came from 0 with tag 0: 'Hello, I'm 0, you must be 1'
I'm 3 and this message came from 2 with tag 0: 'Hello, I'm 2, you must be 3'
I'm 5 and this message came from 4 with tag 0: 'Hello, I'm 4, you must be 5'
I'm 7 and this message came from 6 with tag 0: 'Hello, I'm 6, you must be 7'
I'm 9 and this message came from 8 with tag 0: 'Hello, I'm 8, you must be 9'
I'm 11 and this message came from 10 with tag 0: 'Hello, I'm 10, you must be 11'
I'm 15 and this message came from 14 with tag 0: 'Hello, I'm 14, you must be 15'
cmd line history meme
April 16th, 2008
\m/ ~ $ history 1000 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
57 cls
57 cd
48 rake
48 ls
42 emacs
35 exit
34 git
21 *****
18 gst
18 cap
\m/ ~ $
If you're reading this... Tag. You're it!
From 0 to Cruisin in One Script!
April 14th, 2008
This script does assume a few things in order to work properly. If you follow these instructions you shouldn't have any problems. These instructions should be followed immediately after installing Ubuntu or building your Ubuntu 7.10 VPS.
% sudo adduser cruise
% sudo apt-get update
% sudo visudo #add cruise user to sudoers file
% sudo su cruise
% cd /home/cruise
% sudo aptitude install subversion
% svn co https://opensource.thinkrelevance.com/svn/system/ubunu/setup
% mv setup/go_cruisin.sh .
% sudo sh go_cruisin.sh
This will take a while to complete depending on your system. I usually use Slicehost for my VPS needs. On a well equipped Slicehost VPS this script usually takes around 10 minutes to complete. This is the first version of this script and I intend to make some more updates and require less user interaction, but I think this is a good start!Edited on April 14, 2008 to fix svn url and suoders constraints
Make sure you lock the doors!
April 10th, 2008
Linux
*filter
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/255.0.0.0 -i ! lo -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -j ACCEPT
COMMIT
Copy this script to /etc/iptables.rules and load the ruleset.
% sudo iptables-restore < /etc/iptables.rules
You can make sure your ruleset loaded properly by runnning:
% sudo iptables -L
If all is well then save your ruleset out like so.
% sudo iptables-save > /etc/iptables.rules
If you want the firewall to load when the interface comes up you need to add the following to your network configuration (Debian/Ubuntu based systems) in /etc/network/interfaces right before you define your interface.
pre-up iptables-restore < /etc/iptables.rules
OpenBSD
if="rl0"
set loginterface $if
tcp_services = "{ ssh, www, https }"
set block-policy return
scrub in all
antispoof for $if
block in all
pass out keep state
pass log proto tcp to any port $tcp_services
You can turn pf on my adding the follwing to /etc/rc.conf.local
pf="YES"
You can turn pf on from the command line by typing in the following
% pfctl -e
Emacs js2-mode FTW!
April 9th, 2008
- Download a copy and save it somewhere in your emacs load directory as js2.el.
- Fire up emacs and run M-x byte-compile-file RE js2.e
- Add the following to your .emacs file
1 2 3 |
(autoload 'js2-mode "js2" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
|
Cruise Control init script
April 8th, 2008
http://opensource.thinkrelevance.com/browser/etc/init/cruise
Once you have the script just modify it and and the correct paths. Once you have things kosher just do the following.
% sudo mv cruise /etc/init.d/
% sudo chmod +x /etc/init.d/cruise
% sudo update-rc.d cruise defaults
This will make the cruise script executable and add it to the startup and shut down sequences. Now your cruise control can survive a reboot!

