I just have to share this funny quote from the nokogiri website (for those of you that does not know 鋸 it’s a reeeeeeeeaaally good and fast HTML, XML, SAX, and Reader parser).

XML is like violence – if it doesn’t solve your problems, you are not using enough of it. – http://nokogiri.org/

Cheers!

Posted in Programming, Ruby at April 2nd, 2010. No Comments
Tagged with , , , , . Written by: Mathias Stjernström

Introducing Lego

For a while now Mathias and I have been hacking away on our very own web framework called Lego.
But why? I hear you cry, why yet another one, what’s wrong with Rails, Merb, Ramaze, Sinatra, Camping, Rango, Waves, Mack, and so on and so on.
Well, they’re all great but we believe they aren’t dumb enough!
Lego however is about as dumb as it gets, all it knows is how to handle the request/response cycle and leaves the rest up to plugins.
The downside of this approach is that it takes a little bit more work to get it up and running the upside is that you get exactly what you want, nothing more, nothing less.

I’m intrigued, tell me more

So at it’s core there’s lego-core which contains only the bare essentials, a way to set up a controller that rack can run, and a way to extend the various parts of lego.

Future plans include a lego-more gem already setup with commonly used plugins so you easily can get up and running quickly and a central repository of available lego plugins.

A simple application

Provided that you have lego-core installed (gem install lego-core) put the following in a config.ru file:

[cc lang="ruby"]
require ‘rubygems’
require ‘lego-core’

class MyApp < Lego::Controller; end

run MyApp
[/cc]

Run it with rackup and point your browser to http://localhost:9292/ and you should be met by a plain old ‘404 – Not found’, not terribly exiting right? But that’s pretty much all lego-core gives you :)

So what about those plugins?

The lego extension system allows you to hook into various parts of the execution chain, namely:

View – For action and view related stuff
Controller – For defining controller dsl’s
Router – Rules for how lego should match routes, must have a self.match_route method which takes a route and an env parameter and return either a two element array containing the env and a hash of match data (or an empty hash if no match data is available) or false

At it’s core, a plugin is a module that responds to register who’s responsibility is to register with lego, following is a simple plugin example:
[cc lang="ruby"]
module SamplePlugin

# Register is called by lego when plugin is loaded

def self.register(lego)
lego.add_plugin :view, View
lego.add_plugin :router, Matcher
lego.add_plugin :controller, Routes
end

# A plugin module we load as a view helper

module View
def h1(content)

#{content}


end
end

# A very simply route helper

module Routes
def get(path, &block)
add_route(:get, {:path => path, :action_block => block})
end
end

# A very simple route matcher

module Matcher
def self.match_route(route, env)
(route[:path] == env['PATH_INFO']) ? [env, {}] : false
end
end
end
[/cc]

It’s about time for a real example!

As we showed you earlier, lego-core gives you a way to set up an application but it don’t know how to map routes to action so let’s expand on the previous application with our newly gained knowledge of lego’s extension system:
[cc lang="ruby"]
require ‘rubygems’
require ‘lego-core’

module Routes
def self.register(lego)
lego.add_plugin :controller, SinatraController
lego.add_plugin :router, SimpleRouter
end

# implements a basic Sinatra inspiered dsl
module SinatraController
def get(path, &block)
add_route(:get, {:path => path, :action_block => block})
end
end

# Implements a very basic mather rule
module SimpleRouter
def self.match_route(route, env)
(route[:path] == env['PATH_INFO']) ? true : false
end
end
end

# define an application
class MyApp < Lego::Controller
plugin Routes

get "/" do
"Hello from /"
end
end

run MyApp
[/cc]

As before, run it with rackup and point your browser to http://localhost:9292/ and this time you should be greeted by “Hello from /”.

Don’t repeat yourself

If you have a plugin you want to use in every application, then consider defining it globally:
[cc lang="ruby"]
Lego.plugin MyPlugin

# or group multiple plugin calls in a config block

Lego.config do
plugin MyViewPlugin
plugin MyControllerPlugin
plugin MyRouteMatcherPlugin
end
[/cc]

Configuration options

Lego also comes with a very simple configuration handler, it basically provides two methods, set and options, lets look at them in action:
[cc lang="ruby"]
class MyApp < Lego::Controller
plugin Routes

set :foo => “bar”, :baz => “quux”

get(“/foo”) { options :foo }

get(“/bar”) { options :bar }
end
[/cc]

As with plugins you can use set globally:
[cc lang="ruby"]
Lego.set :foo => “bar”

# or group multiple set calls in a config block

Lego.config do
set :foo => “bar”
set :baz => “quux”
end
[/cc]

Wrapping up

In conclusion Lego is a ‘Use what you want’ framework that tries to stay out of your way as much as possible and thank’s to it’s modular design, you are free to use your favourite technologies and tools.

Please note that it’s still in a highly experimental stage!

Posted in Programming, Projects, Ruby, gems at January 13th, 2010. No Comments
Tagged with , , , , . Written by: Patrik Hedman

Recently I’ve been working a lot with dates and tonight I had a hard time finding information about how to group a model by date when the model only have a timestamp column.

Lets pretend we have a user model with a created_at attribute which is stored as a timestamp.

If we want to plot a simple graph showing signups per date this is the way to extract them:

[cc lang="ruby"]
User.count(:group => “DATE(created_at)”)
[/cc]

Thats all there is to it. From this you will get an OrderedHash containing the date and count of users for each date.

One small thing to remember if you are using PostgreSQL. You will need the DATE() function in any ORDER/SELECT statements because PostgreSQL will only select/order by fields thats in the GROUP BY statement and this is a pretty healthy behavior that many databases (no names here) don’t care about. Think about it. If you are grouping all users by date and use * as selector how would the database know which username or email address to display?

This is what happens if you try to group by created_at without DATE() ->

[cc lang="ruby"]
>> User.count(:order => ‘created_at DESC’, :group => ["DATE(created_at)"])
ActiveRecord::StatementInvalid: PGError: ERROR: column “users.created_at” must appear in the GROUP BY clause or be used in an aggregate function
: SELECT count(*) AS count_all, DATE(created_at) AS date_created_at FROM “users” GROUP BY DATE(created_at) ORDER BY created_at DESC
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log’
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:507:in `execute’
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:985:in `select_raw’
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:972:in `select’
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache’
from /tmp/app/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all’
from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:255:in `execute_grouped_calculation’
from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:132:in `calculate’
from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:130:in `catch’
from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:130:in `calculate’
from /tmp/app/vendor/rails/activerecord/lib/active_record/calculations.rb:48:in `count’
from (irb):18
[/cc]

And this is the right way to do it:

[cc lang="ruby"]
>> User.count(:order => ‘DATE(created_at) DESC’, :group => ["DATE(created_at)"])
=> #22, “2009-10-25″=>4, “2009-11-04″=>8, “2009-10-15″=>9, “2009-10-26″=>16, “2009-11-05″=>9, “2009-10-16″=>193, “2009-10-27″=>14, “2009-11-06″=>9, “2009-10-17″=>49, “2009-10-28″=>15, “2009-11-07″=>6, “2009-10-18″=>36, “2009-10-29″=>8, “2009-10-19″=>116, “2009-10-30″=>15>[/cc]

As you may notice the Hash does not look ordered. But if you loop over it you will get them in order:

[cc lang='ruby']
>> User.count(:order => ‘DATE(created_at) DESC’, :group => ["DATE(created_at)"]).each {|u| puts “#{u[0]} -> #{u[1]}” }
2009-11-07 -> 6
2009-11-06 -> 9
2009-11-05 -> 9
2009-11-04 -> 8
2009-11-03 -> 14
2009-11-02 -> 20
2009-11-01 -> 10
2009-10-31 -> 6
2009-10-30 -> 15
2009-10-29 -> 8
..
[/cc]

And thats how you group a timestamp field with just its date part.

Cheers!

Posted in Databases, PostgreSQL, Rails, Ruby at November 8th, 2009. No Comments
Tagged with , , , , . Written by: Mathias Stjernström

So, a few days ago I finally decided to give JavaScript a proper chance and as it turns out; All those people who’s been blabbering on about how JavaScript actually is a very powerful language where right all along!

You see, just like Ruby, JavaScript is extremely flexible, for instance, here’s how you would typically loop over an array:

[cc lang="javascript"]
var myArray = [1, 2, 3, 4, 5];
for (var i=0; i < myArray.length; i++) {
alert(myArray[i]);
};
[/cc]

However, in Ruby land we’ve grown to know and love the [].each { |elem| … } way of looping, JavaScript doesn’t have that but fortunately adding it yourself is trivial:

[cc lang="javascript"]
// Extend the Array object with an each function
Array.prototype.each = function(fn) {
// Loop through each element in this (which will be the
// array instance we call each on)
for (var i=0; i < this.length; i++) {
// Call the callback function with it’s context
// set to the current array element
fn.call(this[i]);
};
};

// With our new each function in place we can now iterate
// over an array like this
[1, 2, 3, 4, 5].each(function() {
alert(this);
});
[/cc]

Now, even though this is a very simple example, it does give you an idea of just how powerful of a language it really is, and while it’s not as pretty to look at as ruby, thereof the unfortunate disguise, dismissing JavaScript as a toy language just isn’t viable any more.

Posted in JavaScript, Ruby at October 28th, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

So in order to save your fingers the pain I updated the ffmpeg gem today. You see, previously you had to do this:


convert "finding_that_nemo_dude.avi", :to => "finding_that_nemo_dude.flv" do
...
end.run

Doesn’t look to bad, right? Well, maybe not, but if you pay attention you would notice some repetition here, since the only thing different about the filenames is the extension. So, to keep things nice and dry you can now do this instead:


convert "finding_that_nemo_dude.avi", :to => :flv do
...
end.run

The old way still works if you really want a different filename all together or if you just really like to type :)

Posted in Ruby, Utilities, gems at August 15th, 2009. 2 Comments
Tagged with , , , . Written by: Patrik Hedman

Test::Unit is great but, of course, it’s designed to work everywhere and so it isn’t tailored to your specific domain. Fortunately though, that’s not a problem since adding your own custom assertions is as easy as creating two methods in your test helper.

Let’s say you have the following class:

class Polly
def is_awesome?
true
end
end

And you wan’t to test whether Polly is awesome, which isn’t something you normally would have to test since I obviously am, but bare with me :) So you would do something like this:

class PollyTest < Test::Unit::TestCase
def setup
@polly = Polly.new
end

def test_that_polly_is_awesome
assert @polly.is_awesome?
end
end

Or, you could write a custom assertion to test whether any given object is awesome or not:

def assert_awesome(obj, msg=nil)
msg ||= "Excpected #{obj.inspect} to be awesome"
assert_block msg do
obj.is_awesome?
end
end

def assert_not_awesome(obj, msg=nil)
msg ||= "Excpected #{obj.inspect} not to be awesome"
assert_block msg do
!obj.is_awesome?
end
end

Now you could test awesomeness like this:

def test_that_polly_is_awesome
assert_awesome @polly
end

def test_that_some_other_dude_isnt_awesome
assert_not_awesome @some_other_dude
end

Custom assertions are great for making tests cleaner and easier to read, but don't go crazy with them, testing ones awesomeness, for example, might not be all that usefull :)

Posted in Ruby at August 10th, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

FFmpeg is a great tool for recording, converting and streaming audio and video. It can, however, be quite cumbersome to use. For example consider the following command:

ffmpeg -i some_file.flv -ss 00:00:20 -t 00:01:30 -s hd1080 -aspect 16:9 some_file.avi

Now, even though this is a simple example, it’s still kind of hard to know exactly what it does, so you can imagine what it will look like once you need to accomplish more complex tasks. By contrast, here is the same example using my ffmpeg gem (gem install polly-ffmpeg):

require "rubygems"
require "ffmpeg"
include FFMpeg

convert "some_file.flv", :to => "some_file.avi" do
seek "00:00:20"
duration "00:01:30"
resolution "hd1080"
aspect "16:9"
end.run

This is in my opinion much easier to understand and use.

For more information checkout the documentation and the source code

Posted in Ruby, Utilities, gems at August 5th, 2009. 2 Comments
Tagged with , , , . Written by: Patrik Hedman

I’m not going to explain what MacRuby is but here’s a short description from the projects website:

MacRuby is a version of Ruby 1.9, ported to run directly on top of Mac OS X core technologies such as the Objective-C common runtime and garbage collector, and the CoreFoundation framework. While still a work in progress, it is the goal of MacRuby to enable the creation of full-fledged Mac OS X applications which do not sacrifice performance in order to enjoy the benefits of using Ruby.

So, to get started you obviously need to install MacRuby, but fear not, the official website provides a graphical installer so it’s just a point-n-click operation.
In order for MacRuby not to interfere with previously installed ruby versions it prefixes all command-line executables with mac* (eg, macruby, macgem, macrake and so on) so you’ll want to keep that in mind.

Hello World

MacRuby comes bundled with HotCocoa, a idiomatic ruby interface to cocoa. Using HotCocoa makes it easy to write to write cocoa apps in your favorite text-editor so you don’t have to resort to XCode and Interface Builder.
But enough talking, it’s time for the mandatory “Hello World” app :)

In your text-editor of choice create a file called hello_world.rb and edit it to look like this:

require "hotcocoa"
include HotCocoa

application :name => "Hello World" do |app|
window :title => "Hello World", :frame => [500, 500, 300, 100] do |win|
win << button(:title => "Click Me!").on_action { NSLog "Hello World" }
win.will_close { exit }
end
end

And that’s it, now save the file and run it from the command-line like this:

$ macruby hello_world.rb

Try clicking the button and you should see something like this in the console:

2009-07-31 23:58:11.752 macruby[28261:10b] Hello World

Well, that’s nice and all, but I want something more

Once you start building anything serious, a single file app isn’t really viable. Fortunally though, HotCocoa comes with a generator:

$ hotcocoa my_app

This will create a directory structure for you, with some rake tasks and a skeleton app. You can try it out like this:

$ cd my_app
$ macrake

Where to go from here?

Both MacRuby and HotCocoa are pretty young and so documentation is sparse, there are however a couple of really good examples under: /Developer/Examples/Ruby/MacRuby/ and /Developer/Examples/Ruby/MacRuby/HotCocoa

Posted in Programming, Ruby at July 31st, 2009. No Comments
Tagged with , . Written by: Patrik Hedman

As part of getting my SuppressValidations gem to load automatically when launching
script/console I took some time to configure my .irbrc file a bit and I thought I’d share it.
So here it is in all it’s glory:


require 'rubygems'
require 'irb/completion'
require 'irb/ext/save-history'

# Tell irb how much it should remember and where
# to save it's history
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"

# Simple prompt
IRB.conf[:PROMPT_MODE] = :SIMPLE

# Auto indent code
IRB.conf[:AUTO_INDENT] = true

# This is only done when using the Rails console
if rails_env = ENV['RAILS_ENV']

# Setup a Rails specific prompt
rails_root = File.basename(Dir.pwd)
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:RAILS] = {
:P ROMPT_I => "#{rails_root}> ",
:P ROMPT_S => "#{rails_root}* ",
:P ROMPT_C => "#{rails_root}? ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :RAILS

# This is only done when the irb session and
# rails are fully loaded (from Mike Clark)
IRB.conf[:IRB_RC] = Proc.new do

# Log ActiveRecord calls to standard out
ActiveRecord::Base.logger = Logger.new(STDOUT)

# Setup a [] alias for find so you can say:
# Post[1] instead of Post.find(1)
ActiveRecord::Base.instance_eval { alias :[] :find }

# Require and mixin the SuppressValidations gem
# (gem install polly-suppress_validations)
require "suppress_validations"
include SuppressValidations
end
end

And here’s a sample session:

$ script/console
Loading development environment (Rails 2.3.2)
test> User[1]
User Load (0.2ms) SELECT * FROM "users" WHERE ("users"."id" = 1)
=> #
test> User[1].save
User Load (0.4ms) SELECT * FROM "users" WHERE ("users"."id" = 1)
User Exists (0.2ms) SELECT "users".id FROM "users" WHERE ("users"."username" = 'foobar' AND "users".id <> 1) LIMIT 1
User Exists (0.1ms) SELECT "users".id FROM "users" WHERE ("users"."email" = 'foo@bar.baz' AND "users".id <> 1) LIMIT 1
=> true
test> def some_method
puts "Hello from some method!"
end
=> nil
test> some_method
Hello from some method!
=> nil

Posted in Rails, Ruby at July 31st, 2009. 2 Comments
Tagged with , , . Written by: Patrik Hedman

In my last post I showed how you can install my suppress_validations gem on a per-project basis but that’s a bit cumbersome. Wouldn’t it be nicer if it always was available in the console on every project?
I think it would, so here’s how you can accomplish just that:

Edit your ~/.irbrc (or create it if you don’t already have one):

require "rubygems"

if ENV['RAILS_ENV']
IRB.conf[:IRB_RC] = Proc.new do
require "suppress_validations"
include SuppressValidations
end
end

And thats it, you can now fire up script/console and start suppressing validations

$ script/console
Loading development environment (Rails 2.3.2)
>> post = Post.new
=> #
>> post.save
=> false
>> suppress_validations { post.save }
=> true
>> Post.last
=> #

Posted in Rails, Ruby, gems at July 28th, 2009. No Comments
Tagged with , , , . Written by: Patrik Hedman

pastbedti.me is using WP-Gravatar