Archive for the ‘ruby’ Category
Feedbag 0.6
I just uploaded Feedbag 0.6 to Gemcutter and GitHub.
Just a couple of small nice additions to this version:
- The undocumented args[:narrow] option has been disabled until further notice.
- A nice little commit from one of Feedbag's forks, by Patrick Reagan.
- Added an executable to find feed URLs directly:
Sometimes you need to find the feed for a URL quickly, not from a script. What I do, and what someone else showed me too, is this:
~ $ irb -- require "rubygems" = true -- require "feedbag" = true -- Feedbag.find "http://stereonaut.net" = ["http://stereonaut.net/feed", "http://stereonaut.net/tag/feed/", "http://stereonaut.net/comments/feed/"] --
But now you can simply do:
~ $ feedbag cnn.com http://twitter.com/compupaisa == cnn.com: - http://rss.cnn.com/rss/cnn_topstories.rss - http://rss.cnn.com/rss/cnn_latest.rss == http://twitter.com/compupaisa: - http://twitter.com/statuses/user_timeline/119479806.rss - http://twitter.com/favorites/119479806.rss ~ $
Enjoy the feedbag executable on your $PATH now!
Setting uid on God processes
I spent some minutes today at work figuring out why a script we use for files and assets propagation wasn't working when fired up under God, but it actually was working when run as its normal user.
The script is a Sinatra application that, upon pings/requests, connects through SSH to different servers on our clusters and execute commands. Details on the implementation are irrelevant here. Since this is automatized, we use key files for the SSH authentication.
When the script was running as the regular user, everything was working fine, but it wasn't under root. So I figured, Net::SSH was trying to use root's private keys file. After reading God's examples I found out that you can also set uid and gid on the watched processes, so that's what I configured:
w.uid = "myuser" w.gid = "myuser"
However, this was still not working. So I made the script print some verification:
puts "My uid is: #{Process.uid} and euid: #{Process.euid} and user: #{ENV['USER']}"
So Process.uid and Process.euid was correctly printing the UID for "myuser", but ENV['USER'] was still "root". I figured that ENV["HOME"] would be the home directory based on the user, "/root", so maybe Net::SSH was still trying to read /root/.ssh/id_rsa, and it was, quoting Net::SSH's :keys option:
:keysThis specifies the list of private key files to use instead of the defaults ( $HOME/.ssh/id_dsa,$HOME/.ssh2/id_dsa,$HOME/.ssh/id_rsa, and$HOME/.ssh2/id_rsa). The value of this option should be an array of strings.
God correctly runs the process with the given uid/gid but it will not change your environment variables. And there's nothing wrong with it, all generated processes on Unix systems will inherit its parent's set of variables. God shouldn't necessarily have to be different, but in case you mess around with a given user's environment variables on a process watched by God, remember this post
Sync your Twitter followers and friends
I have a couple of accounts in Twitter (namely @debian and @planetalinux) that are starting to bring a lot of followers (well, at least some of them). And given that I consider these accounts to be Twitter-polite enough, I like to follow the followers back too; however, this task sometimes gets really hard and it's tiring to go through the followers pages and follow those that I don't follow yet over and over.
So, I spent a few minutes and came up with this simple Ruby script that uses John Nunemaker's awesome Twitter gem.
#!/opt/local/bin/ruby
require "rubygems"
require "twitter"
httpauth = Twitter::HTTPAuth.new(
ARGV[0] || 'yehyeh',
ARGV[1] || 'kissm3'
)
base = Twitter::Base.new(httpauth)
i = 0
(base.follower_ids - base.friend_ids).each do |id|
i += 1
begin
base.friendship_create id
rescue Twitter::General => e
puts "#{e.class}: #{e.message}"
end
end
puts "#{i} new friendships."
i = 0
(base.friend_ids - base.follower_ids).each do |id|
i += 1
base.friendship_destroy id
end
puts "#{i} destroyed friendships."
puts "#{base.friend_ids.size} friends now."
puts "#{base.follower_ids.size} followers now."
What this little code does is exactly that, it will start following the followers you don't follow yet, and it will stop following the people that don't follow you back, right? Got it? It's basically synchronizing your friends with your followers. As said, this is particularly helpful when you are maintaining a community account and want to keep up befriending your kind followers
Handling the exception Twitter::General on line 18 is only done because the twitter gem raises it even when you are trying to befriend an account to which you have already requested friendship (like pending requests to protected updates accounts) or those of suspended accounts (spammers).
Rubx: Twitter's Ruby shell
Rubx, also known as Ruby Boobie, is a nice spoiled girlie bot that runs on Twitter. She listens when you talk to her and when you do, it'll better be with Ruby: She will interpret your tweet in Ruby and reply to you with what your code returns.
How does it work? You send a message to her:
@rubx "The day I was born it was a " << Time.local(1984, "aug", 8).strftime("%A")
And @rubx will reply:
@damog "The day I was born it was a Wednesday"
Go see more about her (examples, FAQ, etc) on axiombox.com/rubx or on her Twitter profile.
As we tested the hack, a bunch of people started interacting with Rubx too, some people calling her Twitter Line Interface Ruby Interpreter!
. See what other people has tried with her here.
Feedbag significantly faster than Rfeedfinder
Alright so Feedbag looks to be significantly faster than Rfeedfinder when tested against different URIs:
user system total real
log.damog.net:
feedbag
0.280000 0.050000 0.330000 ( 1.486712)
rfeedfinder
0.140000 0.030000 0.170000 ( 4.259612)
http://cnn.com:
feedbag
0.200000 0.020000 0.220000 ( 0.703625)
rfeedfinder
0.240000 0.030000 0.270000 ( 1.071508)
scripting.com:
feedbag
0.170000 0.030000 0.200000 ( 0.682292)
rfeedfinder
0.220000 0.040000 0.260000 ( 1.668234)
mx.planetalinux.org:
feedbag
0.550000 0.050000 0.600000 ( 1.636884)
rfeedfinder
0.760000 0.120000 0.880000 ( 3.189143)
http://feedproxy.google.com/UniversoPlanetaLinux:
feedbag
0.030000 0.010000 0.040000 ( 0.696871)
rfeedfinder
0.160000 0.030000 0.190000 ( 1.613874)
As I had previously blogged, Feedbag also can use feedvalidator to get most accurate results. The results above were tested with feedvalidator deactivated, which is the default behavior anyway. When activating it, the following results are seen:
user system total real
log.damog.net:
feedbag
0.390000 0.070000 0.460000 ( 3.434350)
rfeedfinder
0.170000 0.030000 0.200000 ( 2.819837)
http://cnn.com:
feedbag
Feed looked like feed but might not have passed validation or timed out
0.200000 0.020000 0.220000 ( 1.103810)
rfeedfinder
0.200000 0.030000 0.230000 ( 1.036161)
scripting.com:
feedbag
0.220000 0.030000 0.250000 ( 1.282081)
rfeedfinder
0.150000 0.040000 0.190000 ( 1.520435)
mx.planetalinux.org:
feedbag
0.660000 0.050000 0.710000 ( 2.784598)
rfeedfinder
0.760000 0.110000 0.870000 ( 3.984222)
http://feedproxy.google.com/UniversoPlanetaLinux:
feedbag
0.050000 0.010000 0.060000 ( 1.275603)
rfeedfinder
0.170000 0.030000 0.200000 ( 2.067279)
So Rfeedfinder appears to be slightly faster on small pages but even slower than Feedbag with big ones (even when Feedbag calls feedvalidator which makes it to make the request twice!). Also, it's noticeable that Feedbag will return more significant results than Rfeedfinder:
>> Feedbag.find "http://log.damog.net"
=> ["http://feeds.feedburner.com/InfinitePigTheorem", "http://log.damog.net/category/feed/", "http://log.damog.net/tag/feed/", "http://github.com/damog/rfeed", "http://log.damog.net/tag/rfeed/", "http://log.damog.net/comments/feed/"]
>> require "rfeedfinder"
=> true
>> Rfeedfinder.feed "http://log.damog.net"
=> "http://feedproxy.feedburner.com/InfinitePigTheorem"
After this, it really makes more sense to use Feedbag than Rfeedfinder.
The benchmark code can be found here. As I wrote the bechmark test, I did put the Feedbag requests first in order to make it less likely to have better results for Feedbag for a possible cache favoring it, even then, Feedbag was superior.
lib/active_record/base.rb:2808:in `attributes_with_quotes': undefined method `each' for true:TrueClass (NoMethodError)
OK, hopefully this might help someone some time somewhere. If you are getting the error on the title, it's mainly because you are using a changed method on your ActiveRecord model.
I was working with an ActiveRecord model that handles an string with quotes, so when trying to save the model, that exception was raised. The problem is that ActiveRecord uses a changed method internally for all attributes that were modified. When you are using a changed method yourself, you are overwriting it, hence the error. In my case:
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2808:in `attributes_with_quotes': undefined method `each' for true:TrueClass (NoMethodError)
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2706:in `update_without_lock'
Solution, just get rid of your changed method and rename it something else.
Also helpful information, here.
Re: On DebGem
Wouter, I find your thinking on DebGem a bit overreacted. I think you are taking the product and commercial efforts that a company make as the proposed solution we've all been expecting for a similar problem, which is not. You are considering DebGem to be an outcome provided by the Ruby community, which is not, to this issue.
Phusion is obviously not the Ruby community, but part of it. How I see it, it's great: I applaud that more companies take a look at nice technologies and try to provide their own products. Since I do most of my work with both technologies (and others), Debian and Ruby, I find DebGem worth giving it a try, and if it solves the installation problems of some gems on different systems for me, my employer and the systems I maintain, why not pay for it. However that's all you can expect it to do, solve your gem installation problems and that's it, they are not proposing to change how gems are done or how Ruby libraries are implemented as packages in Debian, they are just a bridge, a shortcut, nothing else, nothing more. And if that bridge works and is well built and maintained, hurrah!
Ruby goodies: Modules and methods for my everyday Ruby
I make a lot of Web script processing, whether scraping, webservices, systems administration, etc. Because I sometimes happen to repeat small and useful chunks of code for different projects, I thought that, given making new modules and methods is usually hassleless in Ruby, I should make my own set of methods and goodies I constantly use. Example 1, I sometimes miss Perl's LWP::Simple simplicity where I just pass a URL to a subroutine and get the content on a variable, quick, one-liner. Example 2, extract all links on a given URL on an array that I can then iterate and maybe fetch given the first example. Getting all A links is very easy to do, say with regex or with Hpricot (which should the best way to parse HTML), but most of the time I (and people, I'd bet) need absolute URLs which is fairly more complex (relative, absolute URLs, BASE href declarations, etc, the same case as in Feedbag).
Well, for different cases like that one, I've started my own set of Ruby goodies. If you don't find them useful, I understand, they are mostly for my
Simple installation:
sudo gem install damog-goodies -s http://gems.github.com/
As time and needs pass, I will be adding stuff into it. For the time being, here's both above examples in action:
>> require "goodies"
requiring /var/lib/gems/1.8/gems/damog-goodies-0.1/lib/goodies/array.rb
requiring /var/lib/gems/1.8/gems/damog-goodies-0.1/lib/goodies/lwr.rb
requiring /var/lib/gems/1.8/gems/damog-goodies-0.1/lib/goodies/html.rb
=> true
>> pp HTML::Links.find "damog.net"
["mailto:david-YOUKNOWTHEDEAL-axiombox.com",
"http://log.damog.net/",
"http://historiasdenuevayork.com",
"http://axiombox.com/",
"http://flickr.com/photos/raquelydavid",
"http://last.fm/user/damog",
"http://maggit.com.mx",
"http://twitter.com/damog",
"http://www.facebook.com/profile.php?id=670490388",
"http://www.chess.com?ref_id=1380378",
"http://www.chess.com",
"http://www.chess.com/members/view/damog?ref_id=1380378",
"http://www.chess.com/echess/create_game.html?uid=1380378&ref_id=1380378",
"http://www.chess.com/home/game_archive.html?member=damog&ref_id=1380378"]
=> nil
>> pp HTML::Links.find("http://google.com").first(10)
["http://images.google.com/imghp?hl=en&tab=wi",
"http://maps.google.com/maps?hl=en&tab=wl",
"http://news.google.com/nwshp?hl=en&tab=wn",
"http://www.google.com/prdhp?hl=en&tab=wf",
"http://mail.google.com/mail/?hl=en&tab=wm",
"http://www.google.com/intl/en/options/",
"http://video.google.com/?hl=en&tab=wv",
"http://groups.google.com/grphp?hl=en&tab=wg",
"http://books.google.com/bkshp?hl=en&tab=wp",
"http://scholar.google.com/schhp?hl=en&tab=ws"]
=> nil
>> get "debian.org"
[snip]
>> get("planeta.debian.net")[0, 100]
=> "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
>>
Repository is, as usual, kindly hosted at GitHub on damog/goodies.
Introducing Feedbag: Feed auto-discovery Ruby library/tool
Last week, I spent some time building a good (that I liked) feed auto-discovery tool to use in Ruby for other project I'm building, rFeed. I liked CPAN's Feed::Find, and at some point I made a wrapper class to run a Perl script using such module, however, I wasn't happy by mixing it all. So, Feedbag was born:
>> require "rubygems" => true >> require "feedbag" => true >> Feedbag.find "log.damog.net" => ["http://feeds.feedburner.com/TeoremaDelCerdoInfinito", "http://log.damog.net/comments/feed/"]>> planet_feeds = Feedbag.find("planet.debian.org") [ ... ] >> planet_feeds.first(3) => ["http://planet.debian.org/rss10.xml", "http://planet.debian.org/rss20.xml", "http://planet.debian.org/atom.xml"] >>planet_feeds.size => 104 >>
It makes smart use of relative and absolute bases, hrefs, links, content types, etc. It is also a single Ruby file, so you can grab it and use it on your application. Plus, it only requires Hpricot as dependency. It can find all feeds linked on a web page, but it will return the most important at the beginning of the resulting array, so you will have the important one on the first results (see example above with Planet Debian).
Synopsis, README and a brief tutorial have been placed at axiombox.com/feedbag. You can also take a look at the git repo, hosted in GitHub.
Good looking Irb
Irb is a pain to work with… when you don't know it enough. Fortunately, it can be configured extensively enough to make your Ruby interactive sessions much smoother. Pocahontas asked me to post my Irb configuration:
# ~/.irbrc
IRB.conf[:AUTO_INDENT] = true
IRB.conf[:USE_READLINE] = true
IRB.conf[:SAVE_HISTORY] = 5000
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb_history"
IRB.conf[:PROMPT_MODE] = :SIMPLE
require 'irb/completion'
require 'irb/ext/save-history'
require 'pp'
# load rubygems and wirble
require 'rubygems' rescue nil
require 'wirble'
require 'utility_belt'
# load wirble
Wirble.init
Wirble.colorize
Which makes Irb to look much much better:

But it is not only coloring the features you are getting, but also Readline support, command history saving, tab completion, libraries loaded by default, persistent history with Wirble, etc, etc. as you can see yourself on the very self-explanatory configuration file. Enjoy.
Update: I have to thank my co-worker Galin for pointing me most of these neat features.



