Thin Strand of Search-and-Replace Rails #
If you’re playing with Rails and you want to better understand Ruby blocks, as well as method chaining, Matthew Bohnsack has a great one-liner, which boils to:
Article.find_all.each { |a| a.body.gsub! \ /src="\/(.*.(jpg|gif|png))/, 'src=\"http://bohnsack.com\1'; a.save }
More like three or four lines, but still. He breaks it up, explains each part, with short paragraph-long lessons. I like how code like the above has the feeling of a sed
recipe, but isn’t utterly cryptic.
mfp
For me, the lack of parentheses in the gsub! call makes this harder to parse.
I prefer to drop parentheses when:Anyway this is not a particularly enticing example of method chaining, is it?
Scott
Scott
Woops, the ‘a unless’ part is not necessary. I should not reply before I’ve had my coffee :(
Bohnsack
Thanks for the linkage and the suggestions – update_attribute seems the way to go.
I was just geeked that I got it to work, not really knowing what I was doing. The statement I created was mostly a result of bouncing on the tab key in irb, picking methods that looked good, looking at their inspect output, and then repeating a few times until everything worked.
This seems an important part of the reason why Ruby and the Rails framework are so powerful. Lots of stuff works like you intuitively expect it to.
Neil
If someone wants to explain yet another nifty piece of Ruby code: Quicksort by Tony Hoare at www.approximity.com/rubybuch2/node8_main.html . (I still cannot completely make out the data flow in this script, esp. the nested sorting issue, e.g. how & why [-1, -3.4, ...] would become [-3.4, -1, ...])
Matt
def quicksort( xs ) return xs if xs.size <= 1 m = xs0 # Split-Element quicksort(xs.select { |i| i < m } ) + xs.select { |i| i == m } + quicksort(xs.select { |i| i > m } ) end
line by line:
If the size is 1 or 0, we just return the array; it’s already sorted
Here we choose an arbitrary “pivot” element. This can be any element of the array. In this case we choose the first.
This is a little more complicated. First, let’s figure out what those selects do. The first one selects all elements less than the pivot. The second selects all elements equal to the pivot. The final one selects all elements greater than the pivot. Let’s modify this and use some temp variables.
In other words, we’re returning a list of all the elements less than the pivot, sorted, then all those equal, then all those greater, sorted. This is classic divide-and-conquer recursion. Quicksort is applied to ever smaller lists until we use it on lists of one or zero elements, and we hit the terminating condition.
OK, I’m not sure if that helped at all :)
Matt
Oops, messed up the formatting on that first bit.
Neil
Wow, thanks Matt for this ultra quick response! Great going!
Tsela
Hehe, it’s funny how this definition of quicksort is a direct translation of how one would write it in functional languages like Haskell. It’s one of the strengths of Ruby that it supports all programming styles (structured, object-oriented, functional, you name it) without ever having to resort to ugly hacks :) .
moui
To get a handle on the data flow you also can insert: puts i < m etc. or just after def quicksort(xs): puts xs.size; print xs; print ”\n”.
Bel
The internal sorting of the array of numbers contained in the less and more temp variables is accomplished by the nested quicksort(xs.select…)functions. Each of these functions has the return-if condition but sets its own m=xs(0) pivot element! (The functions can be called nested because they are enclosed in def quicksort(xs)...end)
Comments are closed for this entry.