Tuesday, 26 February 2013

Ruby ARGF and the "<" operator

One of those things I've always should have known but somehow skipped when first read about ARGV and ARGF on Ruby.

ARGF will give you file handlers and content of all files passed to the script, but it assumes that all arguments present in ARGV are in fact files.
So if you want to be able to call your script like so:

./myrubyscript 100 file.txt

Than in the code you must have:


somvar     = ARGV.shift.to_i
filelines  = ARGF.readlines


How about, if for some reason, you want to call your script like so:

./myrubyscript 100 < file.txt



somvar     = ARGV.shift.to_i
filelines  = ARGF.readlines



It's the same code! Don't you love Ruby?

The workings:
The arguments passed to your script are stored in the ARGV Array, one argument per element. ARGF assumes that any arguments that aren't file names have been removed from ARGV.
It took me more than it should have to find this little page.

Monday, 28 January 2013

Installing Musique on Fedora

There's this music player called Musique and it looks very pretty (and macish according to the gf), it has the looks I'd like all my music players to have - artist photos, I mean, c'mon, it's 2013, can we have enough pixels, memory and bandwidth on our desktops and laptops to navigate artists by artist photo! Why can I only do that on my phone?

Anyhow, on Linux they provide the binaries and I've kinda failed to get them to work, probably dependencies, but they listed some kind folk packed it for Open Suse. so I took their src.rpm and and did a few tweaks.
First I fixed the name of the requirement for "qt-devel" as it differed from the Open Suse one.
Second I removed build requires for "update-desktop-files" since it appears to be a Suse thing to do stuff with the desktop, I didn't bother looking for a replacement as I don't want it to add desktop files.

Next I compiled, installed, and it popped up on my Applications -> Sound & Video.

Here is a link for .src.rpm and rpm file in case you want it.

PS: For a while the sound was really bad, but thanks to the author I discovered it was a problem with phonon-backend-vlc, so I added a conflicts with to the spec.

Wednesday, 16 January 2013

TIL About Ruby class and modules namespacing

Today's post is courtesy of Captain Obvious, but still I wasn't sure and just HAD TO experiment.
It's simple, if you have a Module A with a class A::B inside, when you include A into class C, C::B will return A::B.
C::A will return A with a warning.

Friday, 11 January 2013

Bundler is cool and all, but I like YUM better.

Managing Ruby, its different versions and gems is kinda funny thing, funny as in it has many challenges.
First of all, you might want to handle different projects that work with different Ruby versions and each have a different gem set, so RVM is born and you can change these settings with ease, one less problem - although I do have a co-worker that so far failed to install certain gems with it.

Then there's one of the most annoying problems in Ruby, say your project uses gem "a 1.1" and when you try to deploy with "gem install a" you get version 1.2 and this for some reason causes your application to fail and it fails hard! It's one of the hardest errors to pin-point. Now multiply this problem for each gem and it's dependencies you use, it can really hurt.

That's why most Ruby developers (I use this term broadly, including anyone that programs in Ruby in any way) I know use Bundler and it's great, you get a list of all the gems you have on your system and it freezes the versions you know that make your application works and when you try to deploy it simply installs exactly the same gems you have on your devel machine so you don't have any gem difference problem.
But then you get gems with extensions and they don't quite compile, sure you spend some time doing "bundler install" and then "yum/apt-get install [some lib dependency]" and eventually you're there and all is good. Except if you have some nasty gem like ruby-oci8 which can be very annoying to install and not quite  as they say.
If I still got your attention so far, perhaps it's worth noting that my biggest gripe with these solutions is that they don't solve this problem of gem's unspoken dependencies.

Then you use RVM and Bundler together and all your problems are solved and little or no worries on your side. Although I do hear on occasion that those two have a few kinks working like that, but nothing major.

Then there's what's quickly becoming my favorite way of dealing with gems dependencies and so such: YUM!
It started first as an internal rule of the company I work for, the simple version: all software developed within must be packed in a RPM (for RHEL), and all of it's dependencies, including externally developed libraries (such as gems) must also be packed and available in the company's YUM server.
The reasoning was simple, once the software is sold, one must be able to go to the client's server and do "yum install software" and it will just work. (Later I heard this was because one account of failed installation caused the company to loose millions due to some contract provisions I don't really care to understand.)
While I did find it annoying going through these hops at first, I've been growing into this system and I'm grateful that they actually gave my training on software packaging (which is kinda uncommon for companies in Portugal).

YUM allows us to do some pretty fun things, such as, on a brand new server, I can use yum install to deploy my software with just "yum install" and yes, this does solve my problem of unspoken dependencies.

Take for example, an attempt to install my team's testing library on a brand new ruby installation on RHEL 6:


Notice how the first package in the list is NOT a gem, but rather an unspoken dependency for ruby-oci8. Pretty cool uh?
That also means that I have a greater control of all little things that get installed on the system for my app to work and also that I can purge it with considerable less effort. For instance, "yum remove ruby*" will remove ruby, ruby devel, rubygems, ruby libs, irb, all the rubygems and everything that was installed a dependency of any of those.
Sure RVM let's you easily switch between gem sets, but I can easily switch between "everything sets" - of course that is if I don't mind downloading them all again.
Also, with this you can apply patches to gems that are broken and abandoned despite still being popular.

There's a price for that, like everything in that area, it's knowledge, maybe the knowledge of packing is greater than the knowledge needed for Bundler + RVM, but to fix that, there's a tool, it's called "rgem2rpm" (which I use so much that the latest version, 1.4.9, is the release of a pull request I did on Github), with it, you can simply "rgem2pm gemname.gem" and you get a nifty rpm file. You get a few more options to customize it to your needs, and in the case of gems with unspoken dependencies you can pass an easy to make spec template file (you can use the default template as base for it) and add "requires".
When I took the above screenshot I noticed something was amiss, turns out, the testing version of rubygem-headless that we had on repository was not properly packed, so with 5 minutes to make a template file I compiled a new one and voilá:


See how much stuff you truly need to run the gem headless? Well to be fair, the only true dependency is "xorg-x11-server-Xvfb", all others are dependencies of that.

I know what you might be thinking now, for this to work, you need a yum repo with a lot of gems, at least all the gems you use (and their dependencies), well, yes, right now, I believe that we have more ruby gems as rpm then Fedora's Koji and OpenSuse combined (well, combined is probably an overstatement, but I'm confident we have more than each of them, at least).

All of this is packed for RHEL, they would work on Fedora (and probably others) I'm confident, but not by design.
I have in mind setting up a YUM server and compiling all these gems to Fedora, and providing a way for those using Centos and OpenSuse to use it as well, even when though I think there's little public interest in this, it will would make the setup of my devel computers (and co-workers') much, much quicker.

Edit: I almost forgot to mention, for most people, Ruby is a tool for either Rails or Sinatra web development, with a little bit of effort you can pack your web app into an  rpm and deploy on the production machine with YUM install, then have it start restart the web server (and whatever more you need for it to work, such as running database queries and whatnot) and launch your automated tests.
The more I use it, the more I feel that YUM is a very powerful tool that many neglect in favor of other tools that each do a part of what yum does alone.

PS: I do imagine that APT, PACKMAN, PACMAN and other package managers for the many Linux families are just as capable, but since I started making RPM's for RedHat and that's what I have to deal in a daily basis, I'm bias towards YUM.


Friday, 30 November 2012

Oracle sqldeveloper, openjdk, .xsession-errors and no disk space

The file ~/.xsession-errors is eating all of the file system!
I had this problem happen to me before when I was using Ubuntu, at the time I didn't figure out what the problem was, but I solved it with ln -s /dev/null .xsessions-errors and called it quits. Today however, it happened to me on my Fedora system. However this time I figured it out.
Earlier today I had installed Oracle's sqldeveloper, I tried to lunch it a couple times from the GUI, when that failed I went to the console and typed "sqldeveloper", I was graced with the following message:


Error: /bin/java not found
Type the full pathname of a J2SE installation (or Ctrl-C to quit), the path will be stored in ~/.sqldeveloper/jdk
So I gave it my JAVA_HOME, set some config file so it would ignore the fact that I was using open-jdk and voilá.

Seven hours later I'm getting no disk space errors, wtf? 
Scan tells me that my music folder is the biggest file system hog.... sure I can understand that, but it's not like it's growing right now...
Open up the console, ll -ash and bam! .xsession-erros is 11G! 
I tail the file and the oracle's lovely error message and input request is being written on that file at monitor-flickering speed. 
The command ps -aux reveled to me that I had 3 instances of sqldeveloper open since morning, killed those and the file stopped being written on. 
Now just removed it and all is well.

TL;DR: Bad Oracle! BAD!

Wednesday, 7 November 2012

Complete Guide to install Ruby 1.9.3 on CentOS

UPDATE: These instructions also work on Fedora 16 ( and possibly bellow; on 17+ you should have Ruby 1.9.3 on yum repos).
There are some nice guides out there, like this one, explaining how to do this, but they don't tell the complete story, especially if you're on a clean CentOS install - which is the only explanation I can come up with for the fact that other guides didn't have the same problems I had.


EDIT 11/12/2013: The version listed on the instructions bellow is a bit dated, since this post is now 13 months old, check https://www.ruby-lang.org/en/downloads/ for the latest ruby 1.9.3 patch and replace the patch number (p194) with the latest one on step 9 (wget [...] ruby-19.3-p194.tar.gz).

Steps I ended up following:

#preparing packages
$ sudo yum groupinstall 'Development Tools'
$ sudo yum install -y httpd-devel openssl-devel zlib-devel gcc gcc-c++ curl-devel expat-devel gettext-devel patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel make bzip2 zlib1g mysql-server

#compaling libyaml
$ wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
$ tar xzvf yaml-0.1.4.tar.gz
$ cd yaml-0.1.4
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
#compiling ruby 1.9.3
$ wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
$ tar xvzf ruby-1.9.3-p194.tar.gz
$ cd ruby-1.9.3-p194
$ ./configure
$ make
$ sudo make install
#rubygems
$ wget http://rubyforge.org/frs/download.php/76073/rubygems-1.8.24.tgz
$ tar xvzf rubygems-1.8.24.tgz
$ cd rubygems-1.8.24
$ sudo /usr/local/bin/ruby setup.rb


During the preparation stages a few packages may say they already installed, don't worry.
I'm not sure still if it will work with everything (like rails if that's your thing) but at least 
(Update I've installed both Rails and Sinatra without any problems on top of this setup)
I have been able to install some gems now which by other guides I followed fell short of.

Monday, 5 November 2012

Time Helper 2.0.0 released

Funny how time-helper is older than this blog yet not a single post or page about it here.

I've considered this a new major version because there's no guarantee of compatibility with previous versions, in a couple features.

About version 2.0.0

I've changed the =~, the old way was just stupid (no one else to blame but me here), the new version just compares two Time objects and see if they are within an acceptable distance from each other in seconds, defaults to 300 (5 minutes).
So where you'd have a symbol as first argument you now have a Fixnum. Also added a sanity check for the second argument.

Completely removed the #parse integration in #strtotime, this means that if you were using #strtotime as both it won't work, as such, it reduces the memory footprint of this gem (by not requiring stdlib time)  for those who don't want .parse - which is most of the people that I've made this gem for (including myself).

And yes, this gem still doesn't care about American date format (mm/dd/yyyy), because it's silly.

I've already found a couple issues that need to be fixed:
  • Documentation for =~ doesn't completely reflex the changes.
  • Time.valid_datetime? returns true for more than intended inputs.