.

An Injoke Explained

Ok so I know that Eigen Class is the name of the blog from the guy who brings you RCOV. I had no idea it was actually a reference to a class concept in Ruby. I figured I’d share.

From RedHanded » sneaking Ruby through the system

the term eigenclass, the People’s slang for (class < < self;)


A Programming Puzzle For You Weekend

Facebook | Programming Puzzles

Your name is Randall, former NASA roboticist and all-around smart guy. You and fifteen friends are on your way to see a movie about velociraptors and math

.
I’m thinking about playing with this in Ruby….


In Case You Have A Lot Of Python Libraries

I have to wonder what the performance is like - but here is a novel solution to the problem of having a Python library and needing to access it from Ruby….

Ruby/Python Documentation

Ruby/Python is a Ruby extension library to embed Python interpreter in Ruby. With this library, you can use the libraries written for Python in your Ruby scripts.


Calling one Rake task from another

Rake User Guide |

This has come up a couple of times for me - and I finally found the reference that answers the question.

The simple form:

task :primary => [:secondary]

task :secondary do
puts “Doing Secondary Task”
end

Is easy to remember - since that is basically Make-ish. Meaning that it sets up the dependency on secondary by primary.

The problem I was having was making a rake task that basically collects a set of existing rake tasks. This happens when I need to do a much of database creation and loading from specific directories.

Here’s that one

task :primary do
Rake::Task[:secondary].invoke
end

task :secondary do
puts “Doing Secondary Task”
end

Now I can stop doing the dependency dance and just setup a task that runs like a normal script!


Fun With Cookies

Sorry - this is actually about Rails - and not those kind of cookies (Thought if you need a recipe you can try Ubuntu Cookies from Make)

I’ve been working on integration with another web app all week. This ended up meaning that I spent a lot of time looking at cookies.

Since most of the time the app minds its own business, I’m focused on flash and session. So I realized pretty quickly that I haven’t actually manually set a cookie in Rails before.

It turns out that it is pretty easy but a little confusing. Cookies follow the standard Rails pattern of session,flash etc.

There is just one thing that might trip you up. Basically you have to think of cookies as a Hash with a worm whole in it. (I didn’t make that analogy but I like it).

Basically if you read from cookies you get was was submitted as part of the request. If you write to cookies you will set a cookie in the browser. The confusing part appears to be that if you say

cookies[:timezone] = “CST”

If you put in

cookies[:timezone]

It will be nil. This is because you didn’t get that cookie on the way in. Make sense? Yeah I think the same thing. I figure it exists that way because most people don’t end up messing with them very much.

So in my case I actually needed to set a more complicated cookie. It needed to be accessible to all machines in a given domain and it needed to expire in 12 hours.

It turns out it is pretty easy to do both

cookies["TIMEZONE"] = {:value => “CST”, :expires => 12.hours.from_now, :domain => “.economysizegeek.com”}

Pretty simple - once you know what the options are. Of couse as soon as you start adding stuff like this you end up needing to be able to test cookies. In my case, the mock authentication system had some problems as a result.

Fortunately, Herryanto Siatono came to the rescue with Functional Test with Cookie

So now not only are cookies easier to work with in the app - they are easy to setup for tests as well.


Make Mine Tikka Masala

Sometimes I run into things that I can tell have some serious power and usefulness - if only I could fully wrap my brain around them.

An early example in the computer realm for me is Lex & Yacc. Using them you could basically build your own grammar and your own language. I read the Oreilly book but never got over the hump to actually use them to do anything.

Today - it is Currying. In a nutshell, it allows you to take a method/function that requires more than one argument and make new versions that only require one argument.

The article that got me started was over at Shades of Gray

But in th eend he pointed to Murray which is an implementation that is even available as a gem.

It is interesting stuff. There are a few uses I can think of that fall outside of the “theoretical computer science” realm. Namely making it easier to build base functions with a number of arguments in a library and then using currying to build simple wrappers for a given project that always set certain defaults.

Consider this an oportunity to expand your brain before it is slowed by the weight of Tryptophan


Better Late Than Never

[Mongrel] [SEC] Mongrel Temporary Fix For cgi.rb 99% CPU DoS Attack

Apparently there is an easy way to DoS Mongrel.
In the interim - you can do the following to address the issue


sudo gem install mongrel --source=http://mongrel.rubyforge.org/releases

Guess that means there will be a never version of Monrel released soon - which will hopefully also fix the bug with Content-Lengths.


Magic Migration….To Hell

I got hit by this today and it was so confusing that it took me a long time to sort out. That makes it a prime canidate to post here to make sure it doesn’t get me or you ever again.

I’m a huge fan of the migration system in Rails. It makes it very easy to track changes to you database schema. That’s a good thing!

The issue I ran into today was this - I have been working on my workstation at home for several days. It meant I generated both a lot of code and a lot of tests.

Today I showed up at the office -

svn update
rake setup_test_db (It's a custom task that has actually been superceded by a series of commands in standard rails)
rake

This should bring my laptop up to date, reload the test db, and run all tests. This helps me make sure everything is still on track. Immediately, a huge batch of tests failed - because they couldn’t find the tables I had recently created. After a heck of a lot of head banging - I found the solution.

I was hit by a bit of the old Rails magic. As far as I can tell, the version your test system is going to fixate on is set by your development db.

Small disclaimer - this happened on Rails Edge it may or may not hold true for the current offical release

So in my case, I started running the tests before I touched the development db. That meant that the test db migrated back to the version that was stored in my development db - which was three versions lower than the current one.

The solution was to

rake db:migrate

That brought the development system up to spead and then the tests ran flawlessly.

So if you do revert your development system to a previous version be prepared for the tests to work on that version as well.


Soap (Rails) + Soap (Python) == Dirty Water

For a project I’m working on I have to provide web services via Soap in Rails. The consuming client is SOAPpy (Python).

I hit two different problems and a solution that I wouldn’t mind feedback on.

The first one is that when you post via SOAPpy you get this header


Content-type: text/xml; charset="utf-8"

That generates an error along the lines of

XSD::Charset::CharsetConversionError (Converter not found: X_UNKNOWN -> UTF8):
/usr/lib/ruby/1.8/xsd/charset.rb:112:in `encoding_conv'
/usr/lib/ruby/1.8/xsd/charset.rb:102:in `encoding_from_xml'

The source of the problem is that SOAPpy is putting quotes around the charset. I won’t tell you how long it took me to figure that out. I don’t know if this is a bug in SOAPpy or in Rails because I don’t know if it violates the standard to put it in quotes. (If you know let me know - it will help me figure out who to submit the bug to) In the interim I figured I’d need to fix this.

The other issue is related to Mongrel. For whatever reason when Mongrel talks to SOAPpy it ends up putting the Content-Length header twice. SOAPpy stores it as a list - which then causes it to blow up. I don’t know if that is really a bug on Mongrel’s part because again I don’t know the standard. I submitted a bug anyway.

AS you can see these are problems specifically in interacting with SOAPpy. I don’t have control of the other side so I needed to fix it on the Rails side. So if you have feedback - please keep in mind that I CANNOT modify the Python side unless the SOAPpy project itself releases the update - which since the current version is from 2005 - seems unlikely.

So my solution involved Opening A Class(aka Monkey Patching)

Before we go further let me just say that this strategy is very powerful. Like all powerful things it can be very dangerous. First you are modifing the behvior of something standard to do something different. That means that when someone else tries to use your code - or when updates come out - if you are not careful you may earn your self a lot of time in the penalty box when you can’t figure out why something doesn’t work for you. The goal of the process as described here is to make it at least possible to figure out where to look.

First of all, most of the structure is actually from another developer I’m working with (Thanks Ryan!) - but I figured I’d spend some time documenting it with my solution to the Soap problem.

In the rails project we now have a directory /add/core_ext

This is where all modifications go.

At the very bottome of config/enviroment.rb the following line is added

Dir["#{File.expand_path(RAILS_ROOT)}/app/core_ext/*.rb"].each { |file| load file }

If an object acts weird you get to look here first.

Second - the modifications are added in a module named in a way that shows that modifications are being made.

This allows me to issue a command like this to console

ActionWebService::Protocol::Soap::SoapProtocol.ancestors

Which returns

[ActionWebService::Protocol::Soap::SoapProtocol, SoapProtocolExtension, ActionWebService::Protocol::AbstractProtocol, Object, ObjectExtension, Base64::Deprecated, Base64, Kernel]

You can see the SoapExtension in the list. I’m sure as we deal with this more we will standardize more to make it easier to figure out if something has been opened by something else.

Now on to the code.

I create a file in core_ext called soap_protocol.rb

module SoapProtocolExtension
    #Required to handle CONTENT-TYPE that wraps the char set in quotes
    def custom_decode_action_pack_request(action_pack_request)
        return nil unless soap_action = has_valid_soap_action?(action_pack_request)
        service_name = action_pack_request.parameters['action']
        input_encoding = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE']).gsub(/["']/,”")
        protocol_options = {
            :soap_action => soap_action,
            :charset  => input_encoding
        }
        decode_request(action_pack_request.raw_post, service_name, protocol_options)
    end
end

ActionWebService::Protocol::Soap::SoapProtocol.class_eval {
    include SoapProtocolExtension
    alias old_decode_action_pack_request decode_action_pack_request
    alias decode_action_pack_request custom_decode_action_pack_request

}

The top part defines the function that actually handles the quoting.

The bottom part opens the class and includes the new method. Then it uses the alias method to move the old method out of the way. Then it moves the custom method into place. I could have probably reduced code by just modifing the HTTP_CONTENT_TYPE and passing it on to the old method. (Assuming I stick to this path that’s probably what will happen).

The second patch is in a file called mongrel.rb. I had to add a little bit more logic because Mongrel isn’t always present at startup (Hello webbrick). I also ended up putting it inside the Mongrel module to give it access to constants and other info related to Mongrel

if Module.constants.include?(”Mongrel”)

module Mongrel
        module Mongrel::HttpResponseContentLengthBug
            def custom_send_status(content_length=@body.length)
                if not @status_sent
                    #@header['Content-Length'] = content_length unless @status == 304
                    write(Const::STATUS_FORMAT % [@status, HTTP_STATUS_CODES[@status]])
                    @status_sent = true
                end
            end
        end
    end
    Mongrel::HttpResponse.class_eval {
        include Mongrel::HttpResponseContentLengthBug
        alias old_send_status send_status
        alias send_status custom_send_status
    }
end

Once the bug in Mongrel gets fixed I’ll remove this modification. But until then I can continue working on the system. Anybody else done anything like this? Am I going down a dark path?


Fun with TimeStamps

I can’t tell yet if this is an issue I just never ran into or if it has something to do with running Edge Rails (more testing and I’ll know)

Anyway I ran into a problem today working on some code were I actually need to set the created_at/updated_at fields for a given object. This made it easier to make sure that the search returned the right objects.

I kept doing

my_obj = MyClass.new(:name => "hello", :created_at => Time.gm(2006,1,1,10,12,13),
:updated_at => Time.gm(2006,1,1,10,12,13))

The updated_at always got set to now(). Which defeats the purpose. Turns out there is a simple way to turn off the Rails magic

MyClass.record_timestamps = false

That line of code turns off auto settting the magic fields. This let me set the stamps to what I wanted - and then I just turned it back on after the creation was done. (if you don’t it will be turned off for all tests which is probably not what you want.)

You can also add this if you have one class you never want to use auto timestamping

class MyClass < ActiveRecord::Base
self.record_timestamps = false
end

The above is from active_record/timestamp.rb

Just one of many nooks and cranies I’ve fallen into this week. If I can I’ll put up my notes on the joys of Monkey Patching with web services.


    You are currently browsing the Economy Size Geek weblog archives for the 'Ruby' category.
    Previous Entries » Next Entries »
    Categories
    Archives

    .