Below you will find pages that utilize the taxonomy term “Ruby”
look ma no hands tweeting with your voice
This is just another one of those boring weekends where I felt the need to hack on something.
If you follow Google Chrome's blog you're probably aware of this little nifty feature they started to implement in their latest builds: HTML5 voice recognition.
And that's when it struck me: "Hey, what if I use that and tweet with my voice instead of typing?"
The result of this hacking session is LoudParrot, a sample Rails app that shows how to do just that. You will need a fairly recent build of Google Chrome -beta - which you can download here.
You can get the source on GitHub.
ide review rubymine
Since I started working with Ruby about 4 years ago, I've used quite a few text editors and ide's: RadRails, gedit + plugins, TextMate and Vim.
TextMate is the one I've used the most and it's been ok for a long time. Until you realize you need half a dozen bundles to make it really useful for ruby development. Obviously the same goes for Vim and gedit.
Oh, and forget about refactoring. In these tools refactoring equals regex global replace. So if you need it, well, forget it.
That's when I decided to give RubyMine a fair go. I've been using it heavily for a while now and I must say I love it!
What pissed me off about RadRails when I first tried it was the speed. It was too slow, something people take for granted when running java based IDE's.
However this is not true for RubyMine. You DO take a hit on startup, nothing major, but once it's done, it's a breeze.
I've compiled a list of my favorite productivity shortcuts and features. Hope it'll be useful to someone else.
Productivity Shortcuts
Navigation
Ctrl + Tab - File Switcher
Cmd + Shift + T - Switching between implementation and test works perfectly. Even in a pure ruby project
Cmd + Shift + F12 - Expand/restore editor
Alt + Shift + N - Go to model/view/controller
Alt + F1 - Show current file in other views such as the project tree (scroll to file)
Cmd + Shift + N - Open file
Cmd + Alt + Shift + N - Open symbol - across files
Alt + F7 - Find usages - when on a method, variable, etc…
Running/Debugging
Ctrl + Shift + F10 - Run current [test] file. When inside a test method, run that single method.
Ctrl + Shift + F9 - Same as above, but in debug mode.
Shift + F10/Shift + F9 - Run/Debug last action executed
Alt + R - Run rake task
Refactoring
Cmd + Alt + N - Inline variable/ method
Cmd + Alt + M - Extract method
Shift + F6 - Rename
F5 - Copy current file as...
Editing
Cmd + Y - Delete line
Cmd + D - Duplicate Line/Selection
Alt + Mouse - Column selection
Cmd + Shift + (Up Arrow|Down Arrow) - Moves de line or selected block of code up or down
Features
Code completion - It's fairly accurate and pretty fast. They've done some good yak shaving around this area.
Debugger - The debugging interface is an absolute beauty. Saved me a lot of time where I'd have used puts statements or googled to re-learn how to use ruby-debug instead. Definitely worth checking out.
The bad stuff
It is not free - unless you are a committer to an open-source project. But it's not expensive either.
It is a bit slower - but not that much. The performance hit is insignificant compared to the added value.
Regex file open, TextMate style - What can I say? I do miss this.
Wrap highlighted text - In TextMate, if you highlight a word and press ", [, {, ( or # it surrounds the word with the respective combination of quotes, brackets, etc... Another missed feature
Wrapping up
It's probably soon to say it but so far RubyMine has been my missing Ruby IDE. And I'm very happy with it. :)
clouds against the floods presentation available
Last Tuesday I gave a short presentation on the whole Clouds Against the Floods thing at the Ruby on Rails Oceania User Group here in Sydney.
Those guys are awesome and they recorded the talk - thanks guys!
If you'd like to download the slides, they're available on Slideshare.
Enjoy! ;)
update to appconstants it can now be used as a gem
This is just a quick post to let you know that AppConstants can now be used as gem!
Just add it to your Gemfile and 'bundle install' it:
#in your Gemfile
gem "app_constants"
#in the console
$ bundle install
$ rails generate app_constants
#then follow the instructions on-screen instructions
It can also be used without Rails. Check out full instructions on the GitHub repository.
Feedback welcome :)
clouds against the floods
I think by now everyone's heard of the hard time the guys up in Queensland, Australia are having because of the recent floods. People have lost their lives and many others have lost their homes and businesses, product of years of hard work.
As a result of this massive disaster the Queensland Government decided to run a telethon to encourage donations to help the flood victims. The Telethon aired last Sunday, 09/01/11, on Channel 9 and lasted for 2 hours.
The problem was the existing donations system that the Government had been using so far: it was just not thought out to handle the load we were expecting to have on Sunday.
That's when my employer, ThoughtWorks, kindly offered a hand to Smart Services Queensland in the attempt to make sure they could receive all donations that were likely to come through the web.
After that, on the Thursday afternoon before the event, Phillip Calçado, Ben Barnard and I set off on a mission against the clock: we had a little over 48 hours to develop, test and deploy an application that was expected to handle thousands of users. Not only that but an application that, should it fail, would prevent millions of dollars from reaching the people in need in Queensland. This was a great responsibility but we knew we could do it.
Given the time constraints it was a bit obvious that we would use Ruby on Rails for this app. Both because of the productivity it's known for and because we had the knowledge right there. With that out of the way, we had to decide how and where we would deploy this thing. We thought a little about it and came down to to 2 options: Amazon EC2 or Heroku (which is powered by Amazon EC2 under the hood). I pushed hard for Heroku and that's what we ended up going with.
Now it was time to get down and dirty and start coding the app. In principle it should be fairly simple. It needed a form where a potential donor would fill out his/her information, giving the option to receive the tax receipt by email or regular mail - more on that later. Upon clicking submit users would be taken to the secure payment gateway website where they could input their credit card number and finish the payment, after which they would be taken back to our app with a success - or an error - message and a transaction number.
Now this work flow has a couple of implications: First, all emails would have to be sent in the background so as to not interfere with the website performance. We were expecting to be sending thousands of them - workers anyone?
Second, the payment gateway integration would have to be developed and tested from scratch. Up until now the Queensland Government integrated with it in a different manner that could not be reused in this case.
And most important of all, although simple in concept, we had no idea of the load we should be preparing for. There was just no data from previous telethons. Thus we decided to prepare for the maximum we possibly could.
As we developed the application we deployed continuously to Heroku in order to test the payment gateway integration, benchmark the app using Apache AB, setup cache headers - Heroku uses Varnish - and find bottlenecks.
Email was one of these bottlenecks and that's why we decided to handle that in the background using Delayed::Jobs.
Since the first deployment, we also tweaked a couple of things at Heroku, such as migrating from their free PostgreSQL offering to a dedicated instance that we believed would both take the load and have plenty of room for all the data - as I write this post, we are already well over the 5MB limit they offer for free.
Long story short, by Saturday evening the website was up and running on 5 app instances, a 6th instance running background jobs - sending emails - and a dedicated PostgreSQL database server.
As Heroku is outside the Government network, their SMTP server was a no go on the short term so we also integrated the app with SendGrid, an email delivery service that fitted perfectly our needs - although the site got so much traction that we went over our monthly quota with them. But the nice guys from SendGrid increased our limit after I opened a ticket explaining the situation!
As for performance we used NewRelic to monitor the application, which Heroku also makes a breeze to integrate with.
We all went home to rest and get ready for Sunday, the day of the Telethon, when we would be monitoring the app throughout the day. We were all excited and when the show went live, we started seeing all those beautiful access charts moving like crazy, spiking over 720 requests per minute and being solid like a rock with flat and fast response times throughout the night.
In about two hours we had over AUD$2,000,000.00 (two million) donated through our website.
Since then the number of transactions dropped but has stayed constant and as of today we've received AUD$25,438,518.32 (over 25 millions of dollars) that will be donated to the flood victims in Queensland.
Oh, and the site is still up and going strong so move your fingers and go help: telethon.smartservice.qld.gov.au - there will be heaps of people grateful for your donation.
small update to appconstants
It's been now over a week since we moved to Sydney and everything is just great. We're still house hunting but I got a feeling we'll have a home soon. :)
In the meantime, this morning I got a feature request on github to allow AppConstants to interpret YAML files with embedded code like this:
I haven't needed it myself but thought it would be a nice addition so my latest commit does exactly that. Let me know if you find any issues.
upgrading appconstants to rails 3
Back in January I announced a small but useful plugin called AppConstants, that basically provides a central place where you can store environment specific constants. And since I started using Rails 3 in the past week, I thought I'd make it Rails 3 compatible.
The code is really simple and - as I expected - the upgrade process was quite straight forward.
I'm not gonna write a guide here on how to upgrade your plugins to Rails 3 - there is plenty about that around the web - but instead, just show the steps I went through to upgrade mine. Similar plugins might have a similar upgrade path.
- Generators
My plugin makes use of a simple generator that copies its default constants file and initializer to Rails.root/config and Rails.root/config/initializers, respectively. In Rails 2.x it was located under Rails.root/vendor/plugins/app_constants/generators/app_constants and it was defined like so:
In Rails 3, the generators had to be moved to Rails.root/vendor/plugins/app_constants/lib/generators. Notice the root directory app_constants under generators has been removed as well. And the code was changed to this:
We had three simple changes here:
- The generator now extends from Rails::Generators::Base: This class uses the Thor infrastructure to handle generators. - more info here.
- I had to implement the source_root class method, which basically tells your generator where to find your template files.
- The manifest method is now called copy_config_files - or anything you want.
The way this works is that, once you invoke the generator, Thor will sequentially call all instance methods in your generator class - or the only instance method in the example above. If your generator does a lot, it will allow for a better organization of your tasks.
And that's it! I did change a couple of other things but that had to be changed anyway and are not related to the migration.
For Rails 2.3.x users, you'll find a 2.3.x branch on github that should work for you.
Cheers
learning objective c a ruby analogy
Learning new programming languages is fun. And if it's your 2nd, 3rd...Nth programming language you will eventually look for features you already know and love.
Coming from Ruby - but after having done my fair amount of Java for many years, among other things - I end up looking for features like blocks, open classes and syntax sugar like automatic generation of attribute accessors. These are hard to let go of.
Having decided to learn Objective-C recently, I was delighted to find out that all of these are available - for better or for worse - and wanted to share this analogy with its Ruby counterparts.
- Attribute accessors
In ruby, this class definition
implements for you the getters and setters of the instance variable name.
In Objective-C, the combination of the @property and @synthesize directives provides you with roughly the same result:
Now the compiler is responsible for writing those getters/setters for you.
- Open classes & blocks
Blocks in ruby are the structures that allow you to - among other things - iterate over arrays like this:
Objective-C doesn't have an 'each' method in its root array class (NSArray) but since it does support blocks and open classes, you could just write it yourself:
Yes, I know the syntax isn't appealing, but using it in your program is a bit better:
Given the syntactic differences, the code above is very similar to its ruby counterpart. Iterating over an array is just one of the many things blocks are useful for. Others might include dealing with files, network sockets etc...
Blocks are powerful structures and are not created everyday, but it's nice to know that you can resort to them when the time comes. ;)
hacking rubys syntax
What?
In Ruby you have basically two ways of defining private methods:
I see a small problem with both approaches. In the first one, and the most obvious, is that you need to duplicate the method name as well as add an extra method call - private - just to change its visibility.
The second approach avoids this but adds the risk of accidentally putting a method that is intended to be public under the private section of the source file, which can render an annoying debugging session.
Why?
Personally, I like to have a smooth reading flow in my source files. That means that if the public method_a makes use of the private method_b, I want method_b defined right below its caller, which is possible - but verbose - using the private method call:
But can be somewhat harder to accomplish if you decide to split your source file in sections:
I wanted to be able to define a private method with a single reserved keyword...
How?
What if I could define a private method using this new syntax:
It turns out I can.
Notice the def_p keyword? This is a new keyword I created by changing ruby's parser and that behaves mostly like the def keyword, except that it defines a private method instead.
If you wanna read the code that allows this behavior and try it yourself, download the patch I wrote and apply it to the ruby source code - I patched version 1.9.1-p376.
After applying the patch, just build ruby as usual:
And then try running this script:
You should see the following output:
Happy hacking :)
managing multiple ruby versions
Today I read a nice post - in Portuguese - by Fábio Akita on how to manage multiple ruby versions on your machine. I've tried it once with some tool I can't even remember the name but failed miserably.
But this time things look very different. The tool here is the rvm - short for Ruby Version manager - and it works just great.
Let's cut to the chase and imagine that you, like me, want to run/develop/test your code on both ruby 1.8.7 and ruby 1.9.1. These steps would get you up and running in a few minutes:
Install rvm:
$ gem sources -a http://gemcutter.org/
$ gem install rvm
$ rvm-install
$ echo "if [[ ! -z $HOME/.rvm ]] ; then source $HOME/.rvm ; fi" >> ~/.bash_profile
$ source ~/.rvm/scripts/rvm
Install the ruby interpreters you want to use:
$ rvm install ruby-1.8.7-p160
$ rvm install ruby-1.9.1
Now it's important to notice that at this point you have separate gem installations for each of the interpreters you've installed in the previous step. That said, just go ahead and switch between your interpreters and use your command line scripts - ruby, gem, etc... - as usual.
Switching between interpreters:
$ rvm ruby-1.8.7-p160 #switch to the specified version
$ ruby -v
ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-darwin9.8.0]
$ gem install rails #note I'm not using sudo since the new gem paths point to the user's home directory
$ rvm ruby-1.9.1 #switch to the specified version
$ ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin9.8.0]
$ gem install rails #note I'm not using sudo since the new gem paths point to the user's home directory
And that's it, just go on and install rails, merb, sinatra or whatever rocks your boat!
rvm will work with MRI/YARV, JRuby, Ruby EE and Rubinius. Enjoy and don't forget to check rvm's website for the complete documentation! :)
refactoring for readability
Yesterday I've done something I should do more often: Revisit some code written a while ago for our current project and make it better.
Let's face it. We all write crappy code the 1st time. The difference is in what we do about it afterwards.
We might decide it's good enough and keep moving, or we could (and should!) stop and refactor it!
The code I revisited worked as a refactoring exercise and it's initial version is shown below:
class Jphoto
...
#a few other methods ...
def post_photo(file_data, hotel_id, send_rss, options = {})
file_name = "tmp/#{Time.now.to_i}_#{rand(1000000).to_s(36)}"
File.open(file_name, "wb") do |f|
f.puts(file_data)
end
params = [Curl::PostField.file('photo',file_name),
Curl::PostField.content('hotel', hotel_id),
Curl::PostField.content('source','PhotoUploadTest')]
extract_extra_params!(params, options)
c = Curl::Easy.new("#{service_uri_base}/photoupld")
c.multipart_form_post = true
c.http_post(*params)
if c.response_code != 200
error_msg = "File upload failed with code: #{c.response_code}"
Rails.logger.info error_msg
raise error_msg
end
File.delete(file_name)
hotel = Hotel.find_by_id(hotel_id)
hotel.cache.destroy_all
send_upload_rss(hotel, original_upload_url(c.body_str) , options) if send_rss
end
private
def send_upload_rss(hotel, photo_url, options)
...
end
def manage_images_link(hotel_id)
...
end
def extract_extra_params!(params, options)
params << Curl::PostField.content('status', options[:status]) if options[:status]
params << Curl::PostField.content('upload_source', options[:upload_source]) if options[:upload_source]
params << Curl::PostField.content('uploader_ip', options[:uploader_ip]) if options[:uploader_ip]
params << Curl::PostField.content('uploader_email', options[:uploader_email]) if options[:uploader_email]
end
end
Look at the post_photo method. It has problems in so many levels that it’s hard to start.
Methods should do “one thing” and that method obviously does much more than that, mixing different levels of abstraction.
But let’s start with the easy parts first, keeping in mind that I was aiming for readability.
Lines 7 to 10 seem to be there just to make the reader’s life harder. It’s creating a temporary file through some custom logic instead of using the tools provided by the language. Unnecessary and only pollutes our eyes. My first measure was to use ruby’s TempFile class for this. Better, but we still have a long way.
Right at line 12 it creates some sort of default parameters list, after which it extracts some extra options. I don’t know what that method does but it’s clearly using output arguments, which we should avoid at all costs, as they lead to confusion. This is a big smell as well, and another refactoring step added to my list.
On line 21 starts the code that handles what to do when we get a response_code other than 200 from our request. Apart from the fact that this code doesn’t feel right here, we just happen to know that in HTTP, 200 means success, but that might not be clear to someone looking at the code for the 1st time.
Then the code goes on to delete the temp file, clear the hotel’s cache and send the rss if the rss’ flag is true.
Let there be refactoring….
Geez, how many lines have I used to explain what the code does? Since I don’t wanna bore you to death, here is my refactored version of this method, trying to avoid as much as I can the problems I highlighted previously:
rails summit 2009 im speaking
I'll be speaking at this year's Rails Summit Latin America in Sao Paulo, Brazil. It will be a good opportunity to meet some amazing people and visit friends back home! :)
Overall I'll be spending 12 days in Brazil, with 2 of them dedicated to the conference. The other 10 I'll be in Rio de Janeiro visiting my family and friends. I strongly advise you to spend some time in Rio too, if at all possible. It's an amazing city and you can contact me if you have any questions.
Back to the conference, my session is called JRuby in the enterprise world: Using Rails with legacy code, and will be given in the form of a tutorial. I will walk you through some problems we had while making this kind of integration at my company, focusing mostly on dependency management.
At the end I hope you'll have a good understanding of what JRuby is capable of in a legacy environment.
If you're planning to attend and would like to hear anything specific about JRuby, please let me know, I can try and squeeze in.
C u there!
rails rumble 09
Update: The service is now down while we move it from the VPS provided by Rails Rumble to our own. I'll let you know once it's up.
Last weekend Philip, Pedro and myself got together for this year's Rails Rumble.
We haven't had really decided what to do until a few days before the competition, but I had this really simple idea and decided to go with it. Seems people liked it, given a few positive comments we received.
So, after 48 hours - which were not used to work full-time in the application - The Bird Watcher was born.
The Bird Watcher is a simple way to show the world what's going on on Twitter for any topic you define. Go ahead and take a look at the website to see a live example.
We're planning to keep the service up after the competition is over and we have some nice features lined up to go live on the next release.
In short, it was an interesting weekend and showed me that this team works really well together.
Cheers
jvm language preferences poll results
- Overall results
First off, I'd like to thank everyone who voted on this poll.
With a total of 236 votes, here is the summary of the first two questions:
- Are you currently working with or researching about language alternatives for the JVM? - e.g. JRuby, Scala, Groovy
{% img /assets/images/scala_improvements.png %}
Tooling. The majority of comment urge for better tooling and IDE support. That simple.
- Others
People who chose others mentioned Clojure, Fan and Jython, with a clear advantage for Clojure.
- Disclaimer
This poll has no scientific foundations whatsoever and its sole purpose is to summarize the feelings and personal choices of the people who answered it. If you would like the original spreadsheet with the answers, you can find it here and do your own analyzis.
procs lambdas blocks whats the difference
Do you know?
I didn't. And started to get annoyed by using these terms interchangeably and not really knowing the difference.
There are a few. And they are subtle. I don't think most of us would ever have problems with it but it's the kind of information you'll be glad to know when having those weird behaviors in your code on a Friday at 6:01 pm, just before pushing to production. :)
I guess blocks are the most widely used term in the ruby community and there is little mistake on when to use it:
[1,2,3].each do |x|
puts x*2
end
The code between do and end is a block.
What's important to keep in mind is that Procs behave like blocks whereas lambdas behave like methods. To understand what that means, I highlighted a couple of examples:
- The return keyword
I mentioned Procs behave just like blocks and as such, the return keyword abide to the same rules. This means, for instance, that the latest puts statement on the following code snippet, will never run:
def my_proc(x)
p = Proc.new { puts x*2; return }
p.call
puts "After calling proc" #This never gets called
end
my_proc(10)
>>20
For blocks - and procs-, return means "return from the calling method", my_proc in this case. That's why you don't get to see the output of the puts statement.
On the other hand, in the lambda's example, we get the opposite behavior:
def my_lambda(x)
p = lambda { puts x*2; return }
p.call
puts "After calling proc" #This time, we reach this point
end
my_lambda(10)
>>20
>>After calling proc
Here, return says "return from the enclosing iterator", which, in this case, just returns from the block and continnues the execution of the my_lambda method.
- Argument assignment
On to this second difference, procs and lambdas get more interesting when you can call them with arguments. And that's when another subtle difference between them comes in.
I'll start again with a proc:
p = Proc.new { |x,y| puts x, y}
p.call
>>nil
>>nil
p.call(1)
>>1
>>nil
p.call(1,2)
>>1
>>2
p.call(1,2,3)
>>1
>>2
p.call([1,2])
>>1
>>2
See how procs are flexible? They basically won't complain if you do not provide parameters, provide extra parameters or even send an array as an argument where, as seen in the code above, it unpacks the array and assign its values to the correct variables.
As you're probably guessing, lambdas behave like methods and are much less flexible:
l = lambda { |x,y| puts x, y}
l.call
>>ArgumentError: wrong number of arguments (0 for 2)
l.call(1)
>>ArgumentError: wrong number of arguments (1 for 2)
l.call(1,2)
>>1
>>2
l.call(1,2,3)
>>ArgumentError: wrong number of arguments (3 for 2)
l.call([1,2])
>>ArgumentError: wrong number of arguments (1 for 2)
Ruby 1.9 tip
Despite its name, Kernel.proc returns a lambda in Ruby 1.8. This has been fixed in Ruby 1.9. You actually get a Proc back.
- Reference
The Ruby Programming Language - A must have for any Ruby developer.
helping the jruby effort debugging the source
Wanna help improve JRuby? Make sure you read this post by Charles Nutter first. There he explains how to run Ruby specs with JRuby.
Start with fixing Ruby specs is a great way to get acquainted with the code. And it’s also a important task in order to make sure JRuby is the most complete and compatible ruby implementation out there.
But before you get your hands dirty, it will be a lot easier if you can actually debug JRuby’s source while fixing any specs - or bugs/features for that matter.
railswaycon jruby internals by ola bini
As always I expected a good talk from Ola and once more he delivered it. But this one was different. It might have been even boring to some ruby developers since we saw a fair amount of java code in this presentation. Ola gave us a tour through the main classes that make JRuby possible with a single purpose: so we can check out the code and hack ourselves. You can download his slides here.
If you've been following both JRuby and Ola Bini for the past year or so, you've noticed the trend and evolution of this alternative - and so far the most complete one - implementation of the ruby language. Specially at conferences.
Last year at QCon London, Ola was also talking about JRuby. At Euruko '08, in Prague, Charles Nutter also talked about it. RailsConf in Berlin also had its share. What all these talks had in common is that they talked about JRuby from a user/developer point of view. They were selling the solution. Convincing people to use it and presenting successful use cases.
And as the trend goes on, JRuby is now faced as a true alternative - one that we, btw, believe here at the company as we're actively using it - and it seems that now the call is for help. Help to make JRuby an even more complete and overall better ruby implementation. Charles' call for help was a great step. As he states, it's a good way to get your feet wet. I answered the call and am hacking JRuby myself, having already submitted a couple of patches. Perhaps this was the reason for which I enjoyed the talk the most. I was already familiar with some of the structure and classes in JRuby.
There were 2 more talks about JRuby: The Pleasure and Pain of Migrating to jRuby, by Steven Bristol and Integrating Enterprise Java with JRuby and Rails, Michael Johann. Unfortunately only the first one was a real case experience, where Steven walked through the problems he faced integrating JRuby with an existing java project. Interesting insights.
Michael Johann basically presented a short tutorial on how to integrate rails with EJB3 which, albeit interesting, failed to address issues faced on real life projects, like dependency management. Issues which we have already addressed in a very cool way here and I plan to share it soon. Still deciding how though...
rails readable test names run individual tests from the console
As you probably know, since rails 2.1 you can write test methods in the following format:
test "hotel should return its permalink" do
#your test code here
end
Which is great, as the test name becomes much more clear. But you can't simply run this test easily from the command line. You'd have to run something like:
$ ruby your_test_file.rb -n test_hotel_should_return_its_permalink
It annoys me. And it's not practical either to make the test fail just so you can get the test's real name.
I wanted to be able to just copy and paste the readable name in the console and have Test::Unit do the conversion and run it for me, like this:
$ ruby your_test_file.rb -n "hotel should return its permalink"
So I created readable_test_names_runner. It's a tiny rails plugin that adds this feature for you.
Enjoy.
rails performance scripts profiler benchmarker
There are several ways you can measure your rails application's performance. The techniques range from filling your code with "puts" statements - :p - to fancy ones like NewRelic - which is quite nice, I must say.
But what many people don't know is that rails ships with a handful of scripts to help you out. One of which is called profiler, located under your application's scripts/performance directory.
By default it uses the standard ruby profiler but if you want more speed - and additional reporting options - , consider installing the ruby-prof gem.
So if you execute it without params, you'll get a clue of how it works:
$ script/performance/profiler
Usage: ./script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]
Pretty self explanatory, right?
As a sample code, I have in my rails app a dumb model with a really dumb method I wanna profile:
class Article
def self.find_all_with_delay
sleep 10
self.find(:all)
end
end
Clearly this method doesn't perform well and is a bottle neck in our super application! But let's see what rails' profiler tells us:
$ script/performance/profiler 'Article.find_all_with_delay' 1 graph > text_graph.perf
Loading Rails...
Using the ruby-prof extension.
Thread ID: 109440
Total Time: 10.147995
%total %self total self wait child calls Name
--------------------------------------------------------------------------------
100.00% 0.00% 10.15 0.00 0.00 10.15 1 Global#[No method] (/Users/leo/projects/test/vendor/rails/railties/lib/commands/performance/profiler.rb:24} /Users/leo/projects/test/vendor/rails/railties/lib/commands/performance/profiler.rb:24
10.15 0.00 0.00 10.15 1/1 Object#profile_me
--------------------------------------------------------------------------------
10.15 0.00 0.00 10.15 1/1 Global#[No method]
100.00% 0.00% 10.15 0.00 0.00 10.15 1 Object#profile_me ((eval):1} (eval):1
0.00 0.00 0.00 0.00 1/1 Class#const_missing
10.15 0.00 0.00 10.15 1/1
merb turns 10 and started driving me crazy
As you may already know, Merb turned 1.0 a while ago and I decided to resume my studies to learn the framework.
So I just built a new app with a few resources and fired the migration scripts:
$ rake db:automigrate
And this is what I got:
Loading init file from /Users/leo/projects/merb/my-first-app/config/init.rb
Loading /Users/leo/projects/merb/my-first-app/config/environments/development.rb
~ Connecting to database...
/opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core/adapters/data_objects_adapter.rb:137:in `initialize': wrong number of arguments (8 for 1) (ArgumentError)
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core/adapters/data_objects_adapter.rb:137:in `new'
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core/adapters/data_objects_adapter.rb:137:in `normalize_uri'
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core/adapters/abstract_adapter.rb:44:in `initialize'
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core/adapters/data_objects_adapter.rb:159:in `initialize'
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core.rb:157:in `new'
from /opt/local/lib/ruby/gems/1.8/gems/dm-core-0.9.6/lib/dm-core.rb:157:in `setup'
from /opt/local/lib/ruby/gems/1.8/gems/merb_datamapper-1.0/lib/merb/orms/data_mapper/connection.rb:44:in `setup_connections'
from /opt/local/lib/ruby/gems/1.8/gems/merb_datamapper-1.0/lib/merb/orms/data_mapper/connection.rb:27:in `connect'
from /opt/local/lib/ruby/gems/1.8/gems/merb_datamapper-1.0/lib/merb_datamapper.rb:17:in `run'
from /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0/lib/merb-core/bootloader.rb:99:in `run'
from /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0/lib/merb-core/server.rb:172:in `bootup'
from /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0/lib/merb-core/server.rb:42:in `start'
from /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0/lib/merb-core.rb:169:in `start'
from /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0/bin/merb:11
from /opt/local/bin/merb:19:in `load'
from /opt/local/bin/merb:19
Lovely, isn't it?
After a fair amount of googling around it turns out that there seems to be a problem with the URI parser Merb uses underneath, called Addressable.
As of the installation of Merb 1.0, the installed version of this library was 2.0.0.
The solution? Install a older Addressable version:
$ sudo gem uninstall addressable
You have requested to uninstall the gem:
addressable-2.0.0
dm-core-0.9.6 depends on [addressable (>= 1.0.4)]
data_objects-0.9.6 depends on [addressable (>= 1.0.3)]
If you remove this gems, one or more dependencies will not be met.
Continue with Uninstall? [Yn] Y
Successfully uninstalled addressable-2.0.0
$ sudo gem install addressable -v 1.0.4
Successfully installed addressable-1.0.4
1 gem installed
Installing ri documentation for addressable-1.0.4...
Installing RDoc documentation for addressable-1.0.4...
I haven't figured out the reason for this issue, so please do share if you know. I'll be glad to update the post. :)
understanding ruby threads
This post is just to clarify some confusion I've noticed reading some posts around the web. There is some misunderstanding of the differences between Ruby 1.8 and Ruby 1.9 regarding threads. And the difference between them and JRuby.
So I decided to write this small summary:
Ruby 1.8 - Supports only Green Threads
This means that the ruby interpreter has its own scheduler. No matter how many threads you create in your ruby program, there will be only one native thread on your OS. Therefore, your program cannot take advantage of multiple core environments.
Ruby 1.9 - Supports native threads (GIL)
Ruby 1.9 adopted YARV as the new VM implementation, which supports native threads. This means that now your ruby programs can take advantage of multiple core environments, but no truly parallel execution is achieved.
The catch is GIL - Global Interpreter Lock - and it means that each ruby thread runs on its own native thread, but only one of them can be executed at a time.
JRuby - Ruby 1.8 compatible
I think this is the easy part. JRuby runs on the Java VM, which supports native threads and parallel execution.
On this environment, ruby threads are java threads.
The future
There doesn't seem to be any decision about what's gonna happen on the next versions of Ruby. At least to the extent of my research. But this is today's snapshot of Ruby threads and I hope it'll be useful to some folks.
c u around
dont use rexml i mean it
REXML is the standard XML processing library for Ruby. It's on Ruby's core and is terribly slow.
Yeah, I know it's pretty simple to use, got a nice interface and, again, it's just there. And it is a good library, for most things. But if you, as me, came to a point that processing XML is taking 50% of the time to render a rails action, it's time to change.
My tip? Use libxml instead. The numbers on their home page speak for themselves. Try it yourself, you won't be disappointed. And I'm really happy with the performance increase on our app.
railsconf europe 2008 impressions and highlights
I'm back in Madrid again after the RailsConf and I think it's time to say something about it. :)
First off, the infrastructure provided by the conference was really great. The rooms, WiFi connection, food... Really well organized.
Now to the sessions, highlights:
Tutorials (Tuesday)
- Meta-programming Ruby for fun and profit (Neal Ford, Patrick Farley)
The old and good techniques that made Ruby so powerful. Here Neal and Patrick walked us through the main tricks to meta programming like open classes - and conditionally open them - , dynamically define methods, sending messages to objects and how Ruby can help test your Java code in a much easier way.
I've put the link to the slides but honestly I don't think they're too much useful without the talking.
Sessions (Wednessday)
- EC2, MapReduce and Distributed processing (Jonathan Dahl)
Jonathan explained the theory behind MapReduce using very simple ruby examples, providing the basics on how to distribute and paralelize tasks accross multiple machines.
He also introduced Hadoop, a platform built in Java that "lets one easily write and run applications that process vast amounts of data". What I liked the most was the simplicity he explained this subject. As of today, his presentation is not available online. Stay tuned as I'm gonna update this post with the links, as soon as they're available.
Sessions (Thursday)
- Debugging & Testing the Web Tier (Neal Ford)
If you've been concerned about testing your app's web tier lately, this presentation would probably not show you anything new. Neal talks about the need to debug and test javascript behaviour accross multiple browsers, using tools like Firebug, JSUnit and Selenium. If you have no idea about what these tools are, please stop now and go evaluate them!
We are pretty concerned about testing on my actual job, but selenium tests can be a pain sometimes - a.k.a extremely slow. And what ends up happening is that they are forgotten. Developers only run the test suite if it's not painful and it's lightning fast. Here's is where the highlight for this session comes: CrossCheck.
The idea is to be able to test your javascript code accross multiple browsers without the need to launch them. In fact, you don't even need a browser installed. The negative point is that it's kinda fallen behind because now you can only test older versions of browsers. But since the project is getting a lot of traction, I'm pretty sure this will be solved soon.
Conclusion
My overall impression of the other sessions I attended is that some speakers just didn't have time to properly prepare themselves, what made me think this years's RailsConf wasn't all that I expected.
But I also met interesting people and after all one of the key points in a conference is networking. :)
Definitely worth it though. And that's why I took the time to provide this highlights.
c u soon
railsconf europe 2008 heading to berlin
The title says it already.
On monday I'll be going to Berlin to attend this year´s RailsConf.
This will be my first one and of course my expectations are pretty high!
As usual, after the conference I'll try and give a summary of what happened there, providing as much content as I can.
Anyone else's going??? :)
C u there!
mac os x getting mysql and rails to work
So I couldn't resist and bought myself a MacBook Pro! It's my first week with my new toy and I'm really enjoying it.
But I need to do something useful with it so I started to prepare it to be my new development platform, starting with Ruby/Rails + MySQL: Here is where the fun begins!
After I installed both Rails and MySQL, I fired up a terminal an typed:
sudo gem install mysql
...and here is what u get
ERROR: Failed to build gem native extension.
If you google this error you will find a couple solutions and this is the one that worked for me:
ARCHFLAGS="-Os -arch x86_64 -fno-common"
sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql
--with-mysql-config=/usr/local/mysql/bin/mysql_config
Now, confident enough, I created a sample rails app and tried to create the development database:
leo$ rake db:create (in /Users/leo/projects/test)
dyld: lazy symbol binding failed: Symbol not found: _mysql_init
Doesn't look happy yet huh? This took me a while to figure out but it turned out to be fairly simple.
I have no idea why but after I installed the gem I had the file mysql.bundle in two different places:
/Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
/Library/Ruby/Gems/1.8/gems/mysql-2.7/mysql.bundle
The solution was to remove the first copy of the file. Now everything is working fine at this end!
I really hope this is useful to someone!
rails vulnerability on rexml
REXML, the XML library uses by many ruby apps, including rails, has a vulnerability that requires an immediate patch on whatever rails version you're using.
Details and instructions on the official rails weblog, here.
But basically, this is what you need to do:
gem install rexml-expansion-fix
Then, require rexml-expansion-fix in your rails's app environment.rb file.
why i like ruby 1 alias_method
So you found yourself in the need to override a method but still count on it's old behaviour?
No problem! Override it with your new code, call super and.... Uh oh!! Suddenly this turned into a problem... Let me give some more context.
I was testing Ferret (and the acts_as_ferret plugin) in a project to provide full text search capabilities to our models. One of the things the plugin does is to add a new method to ActiveRecord, called find_with_ferret. That way, every model can use it. Great!
So I thought that would make sense for me to remove all diatrictics from the input text before letting ferret do its job. You know, like removing umlauts and all that.
I could do that by overriding this method with code to remove the undesired chars and then call its older version to finally do the search - something like calling super, but not quite. And I didn't want my models to inherit from anything else than ActiveRecord::Base. That wouldn't make any sense.
alias_method to the rescue!
You know that to redefine a method in an existing class you can open it up and rewrite it. But since you don't wanna loose the behaviour provided by the original method, this is how you can achieve this:
module ActiveRecord
class Base
alias_method :find_with_ferret_original, :find_with_ferret
def find_with_ferret(q, options = {}, find_options = {})
remove_diatrictics!(q)
find_with_ferret_original(q, options, find_options)
end
end
end
And you're good to go. On line 3 you're just giving the original method an alias, making a copy of it.
Then you redefine it the way you like and on line 6 you call the old version to make sure u still got the same behaviour.
Now all my models can benefit of this change without requiring them to call another method nor inherit from another class.
Cool, huh? :)
the biggest rails event in latin america
Behold latin american railers!
This year we will have the Rails Summit Latin America on October, 15th and 16th, in São Paulo, Brazil.
It's by far the biggest Rails event we've ever had, including many of the speakers that were present at RailsConf.
Fábio Akita is also one of the speakers and provides more details on his blog.
If you're a assumed rails geek don't miss the opportunity to hear from the big names and to know a beautiful country like Brazil.
Oh, btw, if you're brazilian, like me, you have no excuse to miss this party!
Enjoy!!!
passenger mod_rails and problems with custom apache installation
This week we started to test mod_rails in a couple of projects where I work on. One in production.
Of course it's too early for any conclusions, but I just wanted to share a couple of problems you might find when the installer tries to compile the Apache module.
In our case, and I believe it is the case of many servers out there, we have a custom Apache installation, what makes the installer not find it and/or not find the Apache Portable Runtime (APR) sometimes.
The first one is easy and is documented here. You just seed to export the following environment variable, pointing to your apache installation:
export APXS2=/opt/apache2/bin/apxs
The second one is a bit tricky but it happened only when I tried to install passenger in another server that had CentOS. In this case, you will also need the following environment variable, pointing to your Apache APR config:
export APR_CONFIG=/usr/local/apache2/bin/apr-1-config
It took me a fair amount of time googling around to find this answer, so I hope it'll be useful for someone. :)
euruko 2008 materials available
As some of you know I went to the European Ruby Conf in Prague, this year.
The event was awesome and it's good to know they finally made available the majority of the slides, here.
They also published Matz's keynote, and more videos from the conference are being edited right now, so stay tuned to their home page!
Enjoy!
a couple of things from here
It's been some time since my last post but here I am! Where? In Spain, of course! Having a great time, I must say.
I arrived last week in Madrid and the past 2 weeks before that I spent basically packing my stuff. There is still some paperwork going on but everything is flowing well.
Besides this little feedback, I was reading this week's issue of the excellent series This Week In Ruby, from my friend Antonio Cangiano. I found something quite interesting, a plugin called HoboFields.
One of the things that bothers me in rails is the fact that by looking at your model classes, you can't tell the fields you have there. Sure, you can look at the migration script. Yeah, you can also load the development environment and inspect the object. It's a pain in the @zz! But this is the way ActiveRecord works...
Other ORM solutions like DataMapper, allows you to define the fields directly in the class. It's a much cleaner and clear way to maintain your models. And you get to know what properties you have just by looking at your classes.
That's exactly what HoboFields adds to ActiveRecord.
You define your properties and its types straight into your model class, and the plugin creates the migration scripts for you. Coming from a java world my self, I find it rather interesting, useful and it also reminds me of the way Hibernate works. You define your mappings with anotations in your class and hibernate just generate the schemas from there.
It's worth a try.
passengermod_rails released
Passenger(mod_rails) has been released.
The idea is to ease the pain on rails applications deployment. I tested myself and in less than five minutes I had my application working behind Apache!
I'm not going to say much here besides the fact that it seems like a really good option for rails deployment and people have been talking about it already, including DHH.
But I do recommend a read on the architecture overview document. Be sure to read it all, specially the part on handling concurrent requests.
To install, "it doesn't get easier than" that.
Good job guys.
jruby db2 xquery bug
Update: Follow up link to this issue on JRuby's Jira, here
As I told in my last post, it was time to give JRuby a serious try. So I took one of our rails projects at work and decided to migrate it to JRuby and see what happens.
We heavily use the XML capabilities of DB2 and this was a huge problem. Every query would work just fine through the activerecord-jdbc-adapter - part of the JRuby Extras . But every Xquery would gracefully fail!
After some debugging I got stuck and decided to get JRuby and activerecord-jdbc-adapter's source to see what was happening.
As I could see, it has a bug -in my opinion - at the java part of the code. The jdbc-adapter is a bridge to allow Active Record to talk with databases through native JDBC drivers, so it's normal that we do have a java part here. At this point, what the code does is to inspect the sql statement sent from ruby and decide if it's a select, update or insert.
I fixed the problem and submitted a patch to rubyforge. I'm not sure if it's the best solution or not, but now I got the xQueries working just fine.
I'd love to hear from people with similar environments whether this patch works for you or not. I'm sure I didn't try every possibility.
If you wanna try it, just drop me a message (e-mail in the About page) and I can send the pre-compiled jar file - for activerecord-jdbc-0.8
You can also just check out the code and compile yourself. ;)
qcon 2008 slides available
Most of last QCon's presentations are available for download here.
Highlights to Ola Bini's on JRuby(pdf) and Randy Shoup's on eBay's architectural principles(pdf).
And while we're talking about JRuby, it's impressive how it's becoming a recurrent and big subject. Fast. It had its own small space at big event like QCon and in the last Euruko in Prague, we had a presentation by the JRuby Core Developers Charles Nutter and Thomas Enebo.
Big companies are sponsoring JRuby's development indirectly or directly, like Sun. And other big companies are endorsing its production ready state, like Oracle, which has a publicly available website developed with JRuby On Rails.
It's past the time to give it a serious try...
why i like ruby or ruby the language of the lazy programmer
This is quite funny. A friend, Perl addicted, is now learning Ruby. He really enjoys the language but made a interesting observation: Ruby is a language for lazy programmers!
Well, I have to agree... You know, I love saving keystrokes and achieving more by writing less. And this is so true with Ruby.
Let me give a really simple example, comparing with java - don't get me wrong... I love java, specially the platform, but it fits well here since I've always been a Java guy.
Imagine you have a Phone class with the attributes number and type, which can indicate whether the phone is a land line or a mobile phone. Then you got an array filled with phone classes and you want to narrow it by creating a new array only with mobile phones.
In Java, such a class could look very much like this:
public class Phone {
private String number;
private String type;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Quite simple, isn't it? But we are telling the compiler many things we actually shouldn't need to. This class is a java bean and as such, among other things, it needs a pair of getters and setters for each of its attributes.
Now, on with our example, the same class, in ruby, looks like this:
class Phone
attr_accessor :number, :type
end
Yeah, I know the feeling. This class has exactly what we need: the two attributes with its own pairs of getters and setters each. But we didn't need to inform it in the verbose way Java has teached us. Cleaner, period.
Now to the code that actually returns the new array containing only mobile numbers. In java, we can do it in two different ways.
Using an ArrayList:
//Create two phone objects, one land line and one mobile
...
// Add them to an array
ArrayListphones = new ArrayList ();
phones.add(land);
phones.add(mobile);
//Return an array only with mobile numbers:
private static ArrayListselectMobilePhones(ArrayList phones) {
ArrayList<Phone> mobiles = new ArrayList<Phone>();
for (Phone phone : phones) {
if (phone.getType().equals("mobile")) {
mobiles.add(phone);
}
}
return mobiles;
}
Or using ordinary arrays:
// Assume the same phone objects here
...
//Add them to the array
Phone[] phones = new Phone[]{land, mobile};
//Return an array only with mobile numbers:
Phone[] mobiles = new Phone[a.length];
for (int i = 0; i < a.length; i++) {
if (a[i].getType().equals("mobile")) {
mobiles[i] = a[i];
}
}
And you're good to go. Actually this code with an ArrayList here only looks good thanks to generics. But this is another matter. Let's take a look at the ruby code that accomplishes de same task:
//Create two phone objects, one land line and one mobile
...
//Add them to an array
phones = [land, mobile]
//Return an array only with mobile numbers:
mobiles = phones.select { |phone|
phone.type == "mobile"
}
See the difference? Java is a great language but too verbose at times. This is a really simple example but if you take the same principle to a bigger app... yeah, you see where I'm going.
The bottom line... Ruby may be the language of the lazy programmer, as my friend pointed out. But I don't mind being called lazy as long as I can type less and be more productive. Do you? :)
euruko 2008 european rubyconf prague
On friday I'll be heading Prague for the European RubyConf.
Anyone is going? :)
Almost 300 attendees already registered for the event. And a few very interesting people will be speaking there like Matz and DHH (this one, through skype).
Besides that, the organization staff is scheduling 2 parties, friday and saturday, for the attendees.
Networking comes to mind, doesn't it? I think it will be a great opportunity to meet interesting and bright people.
So, see u in Prague!
qcon 2008 domain specific languages
Today was the first day of the conference and it started with a tutorial about DSL's with Martin Fowler, Neal Ford and Rebecca Parsons. We also had as attendants Ola Bini, core developer of JRuby, and others. My expectations were pretty high and the presentation didn't let me down. I'll try to put here toghether my impressions and some notes I took while I was there.
Marting Fowler started discussing what DSL's are and giving some examples that many of us use in our day to day Job. Like the XML configuration files in the Java world. It is a kind of DSL, it has it's own keywords and syntax in order to express some information that will be used , for instance, to configure an underlying framework.
The problem with XML is that it becomes hard to see the overall behavior behind it. It's not very fluent to understand the purpose of an XML file just by looking at it for the first time. There is too much "noise". Things that get into the way of the readability. - YAML files are an much more readable alternatives to XML.
The same happens with a standard framework api code. Let's take for instance a sample API configuration code written in Java to tackle the domain of hotel reservations. A framework like this could have the following implementation:
HotelService hotelService = new HotelService();
PersonService personService = new HotelService();
Hotel hotel = hotelService.findById(1);
Person guest = personService.findById(10) ;
Reservation reservation = new Reservation() ;
reservation.setFrom("2008-03-10") ;
reservation.setTo("2008-03-14");
reservation.setGuests(new Person[]{guest});
hotelService.book(hotel, reservation);
Of course implementations of this simple example may vary but we can see here some of the readability problems. One approach we could use for that is to develop a Fluent Interface to wrap this API. This was one of the techniques explored during the tutorial and the actual fluent interface could now look somewhat similar with this:
new Hotel(1)
.book()
.forGuests({
person.find(10)
})
.rooms(1)
.from("2008-03-10")
.to("2008-03-10");
Much more readable, huh? One of the main benefits of using DSL's they highlighted in the tutorial is the simplicity of code you can achieve. You can actually show this code to a business person and he can understand it. This is a kind of internal DSL.
But there is still a bit of noise in this code. The the parenthesis which are not always desirable, and the use of double quotes for dates. But, this is Java code, and Java doesn't give too much room for you on the DSL subject. Here was when the speakers changed their focus a bit to Ruby. It's dynamic nature and metaprogramming techniques provides a powerful flexibility that allows for a looser syntax.
So in ruby the previous interface could look like this now:
Hotel.find(1) .book(1.room).forGuests {
Person.find(10)
}.from(march.10.2008).to(march.10.2008)
We got rid of the double quotes and the code looks more fluent, like a normal english sentence. I doubt a business guy woudn't understand what this code is doing. With this, we can get closer to the business guys, with a common vocabulary, and fill the gap between us.
This is just one of the ways we could have written this code and is not the actual example used in the tutorial. The syntax also really depends on how readable you wanna make your code. I'll provide those later when they release the digital format of the presentation.
So one of the flows that the development of an internal DSL can get is to build a framework and define the DSL on top of it. But we should also keep in mind that DSL's shouldn't be general purpose programming languages. They should be created to tackle a specific kind of domain problem, so we would have a whole system made of small DSL's.
Another interesting subject that was touched is testing. How do you test DSL's?
The suggested approach, and that I think is quite reasonable, is to have separate tests for the underlying framework and another to test the DSL and its parser you can assure you have the expected behaviour of both parts.
This is really just a summary of my thoughts and of what happened there. I'm not going into too much details right now but if you found something too abstract - and it is! ;) - feel free to ask details. I'll be more than happy to help.
This is definetly an interesting subject and now I'll head to play more with all that. :)
PS; This is not the whole presentation, just the best of it from my stand point. Other subjects include External DSL's which can actually involve you coding Lexers, Parsers and Compilers. It's usually not worth the hassle. And it's too complicated anyway, that's why I left it out from this post.
openid
I think I've been really lucky lately. In my new job I'm getting to work with many interesting things and OpenID is just one of them.
We are investing high in Ruby on Rails and we have now a few internal applications in development stages. Our manager wanted the ability to let people log in to our rails applications(for now) using their OpenID accounts.
It was a funny task, as I knew very little about OpenID. The idea actually is really good. Instead of creating a new user account on each new service/site you'd like to subscribe to, you create a single user account in a OpenID provider - like MyOpenID - and use this identity to authenticate yourself in the services/sites that support this protocol.
What do we earn from that? Well, in my opinion, we can get a couple of benefits:
- You don't need to memorize 723 logins and 723 passwords (if you really care about creating different passwords for all of your user accounts)
- You don't authenticate yourself to the service you're attempting to use. This service actually asks to your provider if your identity is valid, and you authenticate yourself there. Nowhere else.
I strongly recommend you visit the OpenID to understand more about it.
But, back to the problem, we needed to put it working in a rails app. And that's when I found the ruby-openid library, provided by OpenID Enabled.
It is a complete library, really well documented that provides an abstraction layer both for consumer and server applications.
My first step was to develop the consumer. That's what you need if you are going to provide your users with OpenID authentication in your web site. The ruby-openid library comes with several samples that really helped me out here. They were developed using Ruby On Rails and are a really good start point.
After this step, I was asked to evaluate the possibility of being a OpenID provider. At first I thought it would be a really complicated task, but again this ruby library had a great example of a simple provider. The drawback is that the samples were developed in an older version of Rails ( < 2.x ) . So I had to freeze the Rails version to 1.2.5 so I could run the provider sample code.
I am now working on porting this code to Rails 2.x, into one of our applications and it's been flowing well so far. Just wanted to share this library for those of you trying something similar. It is really worth a look.
rails 20 xml data type and db2
[2008/04/30] Update: The ibm_db gem has been updated to support the new Rails 2.0 style migration. Now you can just use t.xml and it will work. Look here for more info. Thanks to Mario Briggs for pointing me to the update.
---
In my new job we work with XML data natively stored on DB2. I have done some test with Rails and DB2 a few weeks ago and it's pretty interesting, specially the easiness that Rails deals with XML.
We decided to test some new features of DB2 9.5 and I decided to test them with Rails 2.0.
So I created a new Rails app, configured the database.yml to use the idm_db gem and fired:$ rake db:create
The output is nice but, the database isn't there! I suppose it's something with the gem that needs to be updated. But really don't know about it. It just doesn't work. But this will not hold us down. I will just create the database by hand and keep going with my tests.
After that, I created a new model XmlDocument, which has a column named data, of type XML. According to the new migrations syntax, my model's migration would look something similar with this:class CreateXmlDocuments < ActiveRecord::Migration
def self.up
create_table :xml_documents do |t|
t.xml :data
t.timestamps
end
end
def self.down
drop_table :xml_documents
end
end
Right? Ok, I fired up a terminal and lauched:$ rake db:migrate
The output? Here it is:== 3 CreateXmlDocuments: migrating ============================================
-- create_table(:xml_documents)
rake aborted!
undefined method `xml' for #
Yes, a big nice exception! The new migration syntax doesn't allow you to do t.xml! But please don't ask me why! :p
The solution? Well, although it's weird - imo - , it's also easy. You can mix the new and the old syntax in the same file. So our model's migration will now look like this:class CreateXmlDocuments < ActiveRecord::Migration
def self.up
create_table :xml_documents do |t|
t.column :data, :xml
t.timestamps
end
end
def self.down
drop_table :xml_documents
end
end
And that's it! We're ready to go! I didn't find anything else different so far, besides what I described here. Hope this helps!
rails 20 scaffold
Following the Rails 2.0 hype, I've been playing around with it and decided to share a first impression: Scaffolding is gone!
But wait, before you knock your head against the wall, let me tell you something: I lied :)
Scaffolding is not really gone. It's just changed a bit.
How can I tell? Well, as a good developer I thought: "I'll just create a scaffold with the new version and see what's different"
I fired up a terminal, created a news rails application and generated a new model:$ script/generate model Contact name:string email:string
- yes you can do this in rails 2.0, and these fields get into your model's migration!
Now the I have a new model, it's time for a controller to manage it:$ script/generate controller Contacts
So your controller would look something like this huh?class ContactsController < ApplicationController
scaffold :contact
end
Well, too bad! The method scaffold is gone from ActionController::Base! And I'm not lying this time!
Now that the dynamic scaffold is gone, we're left with the static one.
Ok, let's try it then:$ script/generate scaffold contact
And it won't work again! ;) At the end of the output, you will get something like this:Another migration is already named create_contacts: db/migrate/001_create_contacts.rb
It really means that if your model is meant to be used by a scaffold, you better generate it in the same line. It will fail, afaik, if the model previously existed. Destroy yout model and controller, and execute the following:$ script/generate scaffold Contact name:string email:string
Done! Just run your migrations, startup your server and your new scaffold in rails 2.0 will be working gracefully!
It took me a while to discover this changes because I didn't find it well documented. But maybe I was not looking in the right places. :)
rubyworks production stack for rails
Well, we all know how hard, or at least cumbersome, it can be to set up a production environment to deploy your applications. Besides all the hardware stuff like storages, links, routers you are still left with a huge amount of software configuration to handle. This often includes configuring things like clusters, load balancing and services monitoring - Including notification of interested parts in case of any failure. Pieces of software you have to tie up and make them work together.
But hey, ruby lovers, you may have a better way to get this going! Released by ThoughtWorks, RubyWorks is, as quoted from their website, a production application stack for Ruby On Rails applications. I decided to give it a try and I really enjoyed it.
First of all I didn't want to mess with my actual configuration so I installed a new vm with Virtual Box. It has Ubuntu 7.10 on it, with 256MB of memory.
After installing RubyWorks - instructions on their website -, you get a new skeleton rails app up and running, being served by 4 mongrels that defaults to production environment! Impressed? There is more. A HAProxy is also set up in front of your mongrel servers acting as a load balancer.
Well, you probably want to monitor all that stuff huh? A monit web interface is waiting for your call on port 2812! It monitors all your mongrel servers - four by default - and your HAProxy, allowing you to measure CPU and Memory usage, among other things.
The coolest thing here is that all these softwares you would have to setup by hand are already working together, ready for production! Well, is it?
Going a little deeper, I deployed a database backed application to test this stack's performance.
I used Siege to stress the app and I am very happy with the results! I compared it with a single mongrel running on production env and no proxy at all.
It is worth mentioning that having 4 mongrels running took my vm to 77% of memory usage, while a single mongrel took it to 38%.
ruby on db2 a linux nightmare with a happy end
Although the title might look dramatic, it's pretty close to what I've been through.
I have set up a Ubuntu 64 bits on my laptop last week to do some tests with Ruby and DB2. Oh man, it is not complicated, is it? It shouldn't be, actually.
Too sad that I found this so late! It's a post from a friend, Antonio Cangiano, describing the most common problems you may find trying to set up this environment (Linux + Ruby + DB2). You will probably get it working the first time, if you read it word by word. But if not, here are some extra tips that I can share with you.
- If you installed Ruby using your distribution's package manager, remove all ruby packages completely. After that, install ruby exactly as described in Antonio's post, typing this in the console:
$ sudo apt-get install build-essential
$ sudo apt-get install ruby-full rubygems
After that, you may try again.
- Another problem I found was after getting the driver built. I have written a simple program to try the connection and got this message:
Failed to load IBM_DB Ruby Driver
The thing is that this error really means it was not able to find the file libdb2.so.1 in the /usr/lib directory. Issuing this command may settle things for you - it will create the missing symbolic link:
$ ln -s /opt/ibm/db2/V9.5/lib64/libdb2.so.1 /usr/lib
Good luck!