Workshops am OCDW#3
Mein Kollege Franz macht alle paar Monate in seinem Haus, nahe Eisenstadt und eine knappe Stunde von Wien entfernt, Workshops zu Computerthemen die unter dem Label OCWD laufen. Beim dritten dieses Jahr durfte ich einen über die Programmiersprache Ruby und das Web-Framework Ruby on Rails halten was mir sehr viel Spass gemacht hat. Neben Franz und mir waren noch drei Lernwillige zu Gast von denen bisher nur einer am Rande was mit Webentwicklung zu hat.
Hier die Weblinks zu meinen zwei Slideshows wobei die zu Ruby on Rails dann in den praktischen Teil überfloss wo wir dann diverse Dinge ausprobiert haben.
I18n for the lazy
Why the heck didn’t I read this earlier in the Rails 2.3 docs for translate?
Second, it’ll scope the key by the current partial if the key starts with a period. So if you call translate(”.foo”) from the people/index.html.erb template, you’ll actually be calling I18n.translate(“people.index.foo”). This makes it less repetitive to translate many keys within the same partials and gives you a simple framework for scoping them consistently. If you don’t prepend the key with a period, nothing is converted.
Hire Austrians
This month Dr. Nic suggested Australians for your open job positions but I totally recommend Austrians. And here are my reasons for:
- Austrians are more laid back than Australians. Actually they are so laid back that they are a few positions after Australia in your encyclopedia.
- Austria is on the right, the top side of your globe (or Pizza). That means less travel costs if you like to spend your winter holidays in Norway.
- Austria has no boring deserts like Australia but a great variety of desserts.
- Austria is a safe place for everyone with kangaroos-phobia. And without a coastline you don’t have to fear sharks that kill hundreds of australian rails developers every year.
- There are no dumb jokes about Austrians. They are in fact all true, sad stories.
- Austrians are three-lingual. They talk Austrian, German (in theory) and English. And an Austrian talking English sounds much more funny than a Italian talking English while you still understand the Austrian. German is also in the same family of languages like English or the superior Norwegian.
- Austria has a long and outstanding nautical history. They once owned an actual mediteranian city. Nowadays they retreated from the costly shipping business to concentrate on the rails-fu.
- Austria has Sound of Music, Mozart and Falco. A lot better than Tamara Jaber, Joe Dolce or Jacko. Science says that rails developers write better rspec tests if they listen to Austrian music.
- The Terminator is Austrian. And he’ll find you if you hire an Australian. Gov. Schwarzenegger’s latest action against the economic slowdown is sending californian php devs to austria to train them in ruby on rails.
- Austrians are modest. They are so modest that they let the honor of starting two world wars to the german brothers in arms.
- Austrian is a neutral country like Switzerland but with a higher density of open source ruby on rails developers.
- For every Austrian you can get ten germans for free. Actually in Vienna there are 25% Austrians, 25% former jugoslavia and 50% German. Germans are well known for delivering 95% of code quality as Austrian developers but are 90% cheaper.
- Austria has real alps and not only Australian Alps.
- Vienna Rails developers are very urbane. Last time we went to a Australian pub and drank Belgian beer all night.
- And: Austria is not an isolated island somewhere south.
Disclaimer: I’m German but was raised in a small valley surrounded by Austria and moved to Vienna last year which I’ll never regret.
route of destruction
It’s a common thing that you have a nice javascript-driven link in your rails app to delete an object. Of course you could use a proper button_to but for some reason the boss wants a link. But the usual problem is that with a link_to as rails does it, you will rely completely on Javascript, not nice for old or crappy mobile browsers. The only problem that rails gives you is a missing routes for accessing the destroy action of a controller with a GET request. But, viola, here’s the plugin to solve this: route of destruction. For more see the README.
Oh, and don’t use the plugin.
reading log files
I once worked in a company where the default environment.rb deactivated the log file, and I guess it was just because the were bored by long lines of output they didn’t want to read. The sweet advantages of having a DB admin who checks your db queries before they go live.
general facts and hints
First of all: The less lines per request the better. If you see lines that basically repeat, maybe only some id being different, then you have a problem and should think about eager loading, counter caches and other optimizations. Partial caching for sidebar elements might also be a possibility.
A few example log lines
In the example posted at railsforum.com there are four database queries, one on topics, three on posts (of which one is most likely a find_by_sql or count_by_sql ?). We only have to look at the Load lines, the Cache lines are totally ok unless they come in dozens or hunderts. It takes ActiveRecord some time to generate a final sql query, so try to cache common objects e.g. in an instance variable (See railscast #1) and reduce the Cache lines.
These following two lines are almost the same, time to check all related find and remove the differences so ActiveRecord can cache one of them.1 2 |
Post Load (0.000185) SELECT * FROM `posts` WHERE (topic_id = 3338) ORDER BY posts.id DESC LIMIT 1 Post Load (0.000132) SELECT * FROM `posts` WHERE (`posts`.topic_id = 3338) ORDER BY posts.id DESC LIMIT |
1 2 |
SQL (0.000180) SELECT count(*) AS count_all FROM `posts` WHERE (`posts`.topic_id = 3338) |
more examples??? Please send them in.
Further logfile analysis
There are a few tools but I use only two: The RailsLogVisualizer to see which actions are called often in production mode. And I look at what the longest taking requests are. grep and sort nr are your friend, the logfile is your enemy ;) But at the end, the trick is just understanding the log, sorry about, no way around.
Thanks to a poster on railsforum.com for the idea to this blogpost.
adva_cms first release
It’s been quite a while since I blogged about adva_cms here and in November I even joined the dev team. Just yesterday we finally released the first version for the public and the next one coming soon with more features and fixes.
As I wrote in July and December adva_cms has grown from three applications using the Engines plugin. And while I worked on the event calendar that principle turned out to work quite well. As did for the brand-new engines newsletter and photo album. So, check it out and let us know if you find any bugs :)
rails is merging into merb
well, you coulda put it the other way around but as I didn’t try out merb so far I’m expecting to try rails 3 soon :)
OpenIdAuthentication in detail
I’m currently working on my own little project to fill photolog.at with something interesting and for this I decided to use OpenID only. Dr. Nic is a big fan of OpenID and of course I hearted his advice of allowing one account with many identities
The first OpenID plugin I tried was OpenIdAuthentication which would also support regular loging and I can say: it’s just perfect for me. The reason why I decided to allow OpenID login only is that the application will closely integrate into flickr, which is via Yahoo, one of the many OpenID providers. This way I save the obviously unnecessary authentication system, and a bunch of fields on the User model.
How OpenID works
The idea is very simple, you come to my website, type in your OpenID url, my website will forward you to your OpenID provider and there you might have to login. The OpenID provider then sends you back to my website and if nothing went wrong my website will know a few basic details about you, create an account if not existing yet and you are logged in. It’s very easy and quick, no need to type in data that you already stored at your provider.
In my webapplication most of those steps are automatically done by the OpenIdAuthentication plugin, but if you are sophisticated then you might want to change a few things from the example in the README. For instance, it doesn’t tell you anything about creating a new user, or – Dr. Nic’s favourite – how to assign multiple identities to one user. I’ve added all of those functions to my version of the SessionsController. But first a few lines from the models.
Models
The User model is quite simple, only login, name and email. All three will be gathered from the OpenID provider but you might want to add a edit form.
To comply with the mulitiple identities requirement I’ve added an Identity model which contains the identity_url (this quite replaces password and login in a normal user model) and user_id. A user has_many :identites and each Identity object belongs_to :user (just for the case you still have to look this up…).
The OpenIdAuthentication Plugin adds two models, OpenIdAuthentication::Association and OpenIdAuthentication::Nounce but we don’t touch these.
The SessionsController
Best is to follow OpenIdAuthentication’s README and then replace the SessionsController. Please read me comments and let me know what you think about it.
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 |
class SessionsController < ApplicationController # sadly necessary skip_before_filter :verify_authenticity_token, :only => :create def create if using_open_id? # first difference: we explicitly pass the parameter. Much cleaner anyways than hiding it in the plugin... open_id_authentication(params[:openid_identifier] || params[:openid_url]) end end protected def open_id_authentication(identity_url) # also possible for :required and :optional are %w( dob gender postcode country language timezone ) # have a look here: http://openid.net/specs/openid-simple-registration-extension-1_0.html authenticate_with_open_id(identity_url, :required => [ :nickname, :email ], :optional => :fullname) do |result, identity_url, registration| if result.successful? # successful request, time to check wether the identity already exists identity = Identity.find_or_create_by_identity_url(identity_url) if identity.user.nil? # identity doesn't exist, but maybe the user? We use email as a unique key for this. if user = User.find_by_email(registration["email"]) logger.debug("using user '%s'" % user) # assign identity to an existing user identity.user = user identity.save else logger.debug("creating new user '%s'" % registration["nickname"]) # create a new user for the identity. identity.user = User.create!(:login => registration["nickname"], :name => registration["fullname"], :email => registration["email"]) identity.save end end # log the user in @current_user = identity.user successful_login else # oops. failed_login result.message end end end private def successful_login session[:user_id] = @current_user.id redirect_to(root_url) end def failed_login(message) flash[:error] = message redirect_to(new_session_url) end end |
rails rumble 2008
so, it’s just one and a half hour to till this years rails rumble starts. it’s GMT this year, not PST like last year. sucks a bit as I’m already too tired. But this year I have a proper team, collegues from Lomo and I brought in a good idea for a projects. It’s about intertextuality and for the first time I hope to use it for song lyrics that have a lot of reference to all kinds of other songs or pop culture. a project with future :)
adva_cms
A few days ago I stumbled over Sven’s current project adva_cms which is a cms, mixed from mephisto, beast and signalwiki. The basis is mephisto, with all the pro and cons (aka page caching), everything else is included as plugins with Engine.
I hope to use it for a small community site this month and will post updates here on the experiences with adva_cms.
everything in plastic*
Last month I bought plasticpilots.com from Alex (from plasticshore.com), trashed the expression engine it was running on and wrote a completely new software called plasticairships. The new software is running on plasticpilots for a week now, a few of bugs have been fixed since and improvements in the design been made.
I’m not sure if anyone else will ever find good use for it. Alex and I did a redux version this week, for a workshop he does next month. The redux looks totally different of course, very minimalistic, and it has a few features from feedme (which will get some loving soon).
Btw, plasticairships is running on rails 2.1, so it’s totally covered with named_scopes, the new eager loading and other stuff.
single table inheritance in rails 2.1
With the new “rails 2.1” there was a small but for me important change in the STI that made my life easier. Thanks to divoxx for his enhancement. It didn’t show up in the docs yet but I’ll give you an example where.
The documentation’s example consists of the models Company, Firm and Client, very simple. My real life example (it will be on the new plasticpilots website) consists of a model Comment that I use as an association for Post and Site. So Post and Site have many comments. To save duplication I use STI of course and to keep the directories clean I have Site::Comment << Comment and Post::Comment << Comment (and maybe more in the far future of 2009). Old rails versions did a demodulize the class names so I would have Comment in my type column and a lot of confusion. With rails 2.1 it’s the full class name in the type column and I can kick all the work-arounds I had previously.
ActiveRecord::Base.store_full_sti_class = false
rails 2.1, goldberg but no postgres
Sure it’s a strange combination but mysql is most people’s favourite and goldberg is my very personal favourite.
Anyways, today I was upgrading to rails 2.1.0 and guess what, it didn’t work anymore cause some pg was being required which I don’t have. The problem has basically two causes. First the rails devs added a few lines to the postgresql connection adapter to enforce loading the pg or postgresql gem. Second, goldberg was a bit sloppy with its model monkeypatching. The fix is very simple, just a few changes to lib/goldberg/model.rb basically adding the check that goldberg is using in it’s migration extensions anyways.
You can find my patch over at goldberg’s rubyforge bugtracker
Update: A few more issues came up, so you might just want to git clone git://github.com/TomK32/goldberg.git my github repository into vendor/generators and use it like normal.
recent activities
I’ve been doing a lot of open source in the last two months and you might want to check out the results so far. And besides all that there’s the githorde of course.
FeedMe!
FeedMe! is a RSS planet that was started by Daniel Lindsley and I improved it to match my needs for salzburg-weblogs.net. It’s still incomplete and I will put a few more days of work into.
exabuch
exabuch is a german billing web-app and took over this one as well. I have quite big plans with it, also on a commercial level
plastipilots
My newest investment is this very old design website plasticpilots that I’m about to buy from a guy living nearby (yeah, very big internet). It’s getting a completely new software as replacement for expression engine and the new software will be open source as well: plasticairships. I think it will be very easy to customize for any kind of showcases or portfolio.
jaxdoc: Ruby on Rails docs on AJAX
I became big fan of the jaxdoc generator for rdoc in the last months. It’s amazing to find out that you can extend rdoc to generate the docs (and I really love having docs on my local machine) the way you want it. Jaxdoc provides you with ajaxfied documentations which make searching in the docs much faster. Not to forget that you the source of the methods, just like normal rdoc. There are a few download packages at railsbrain.com and one for ruby core at rubybrain.com. But there’s no howto for creating your own docs, so I hope this example to generate for Rails 2.0.1 is complete enough for everyone. If not, please drop me a note. The exclusions could be defined a bit better I guess. And of course you can include other gems if you want a fat documenation.
1 2 3 4 |
sudo gem install jaxdoc VERSION='2.2.2' cd /opt/local/lib/ruby/gems/1.8/gems/ rdoc -S --op ~/docs/rails-$VERSION --fmt ajax --exclude .*generator.* --exclude .*test.* --include actionmailer-$VERSION activerecord-$VERSION actionpack-$VERSION activesupport-$VERSION activeresource-$VERSION rails-$VERSION |